yellow/system/plugins/edit.php

1936 lines
78 KiB
PHP
Raw Normal View History

2013-04-14 22:41:04 +00:00
<?php
// Edit plugin, https://github.com/datenstrom/yellow-plugins/tree/master/edit
// Copyright (c) 2013-2018 Datenstrom, https://datenstrom.se
2013-04-14 22:41:04 +00:00
// This file may be used and distributed under the terms of the public license.
class YellowEdit
2013-04-14 22:41:04 +00:00
{
const VERSION = "0.7.18";
2016-08-13 15:48:18 +00:00
var $yellow; //access to API
var $response; //web response
var $users; //user accounts
var $merge; //text merge
2013-04-14 22:41:04 +00:00
2015-04-29 07:26:48 +00:00
// Handle initialisation
2013-12-01 11:59:07 +00:00
function onLoad($yellow)
2013-04-14 22:41:04 +00:00
{
$this->yellow = $yellow;
2016-08-13 15:48:18 +00:00
$this->response = new YellowResponse($yellow);
2015-10-06 12:19:11 +00:00
$this->users = new YellowUsers($yellow);
$this->merge = new YellowMerge($yellow);
$this->yellow->config->setDefault("editLocation", "/edit/");
2018-04-29 15:48:46 +00:00
$this->yellow->config->setDefault("editUploadNewLocation", "/media/@group/@filename");
$this->yellow->config->setDefault("editUploadExtensions", ".gif, .jpg, .pdf, .png, .svg, .tgz, .zip");
$this->yellow->config->setDefault("editKeyboardShortcuts", "ctrl+b bold, ctrl+i italic, ctrl+e code, ctrl+k link, ctrl+s save, ctrl+shift+p preview");
$this->yellow->config->setDefault("editToolbarButtons", "auto");
$this->yellow->config->setDefault("editEndOfLine", "auto");
$this->yellow->config->setDefault("editUserFile", "user.ini");
$this->yellow->config->setDefault("editUserPasswordMinLength", "8");
$this->yellow->config->setDefault("editUserHashAlgorithm", "bcrypt");
$this->yellow->config->setDefault("editUserHashCost", "10");
$this->yellow->config->setDefault("editUserStatus", "active");
$this->yellow->config->setDefault("editUserHome", "/");
$this->yellow->config->setDefault("editLoginRestrictions", "0");
$this->yellow->config->setDefault("editLoginSessionTimeout", "2592000");
2017-07-05 10:25:25 +00:00
$this->yellow->config->setDefault("editBruteForceProtection", "25");
$this->users->load($this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile"));
2013-04-14 22:41:04 +00:00
}
2017-02-17 13:52:55 +00:00
// Handle startup
function onStartup($update)
2016-08-18 19:57:07 +00:00
{
2017-02-17 13:52:55 +00:00
if($update) $this->cleanCommand(array("clean", "all"));
2016-08-18 19:57:07 +00:00
}
2014-05-29 21:33:01 +00:00
// Handle request
2017-02-17 13:52:55 +00:00
function onRequest($scheme, $address, $base, $location, $fileName)
2013-04-14 22:41:04 +00:00
{
$statusCode = 0;
2016-06-27 13:28:10 +00:00
if($this->checkRequest($location))
2013-04-14 22:41:04 +00:00
{
2017-02-17 13:52:55 +00:00
$scheme = $this->yellow->config->get("serverScheme");
$address = $this->yellow->config->get("serverAddress");
$base = rtrim($this->yellow->config->get("serverBase").$this->yellow->config->get("editLocation"), '/');
2017-02-17 13:52:55 +00:00
list($scheme, $address, $base, $location, $fileName) = $this->yellow->getRequestInformation($scheme, $address, $base);
$this->yellow->page->setRequestInformation($scheme, $address, $base, $location, $fileName);
$statusCode = $this->processRequest($scheme, $address, $base, $location, $fileName);
2013-04-14 22:41:04 +00:00
}
return $statusCode;
}
2014-01-27 11:30:39 +00:00
// Handle page meta data parsing
2015-04-29 07:26:48 +00:00
function onParseMeta($page)
2014-01-27 11:30:39 +00:00
{
2016-08-13 15:48:18 +00:00
if($page==$this->yellow->page && $this->response->isActive())
2014-01-27 11:30:39 +00:00
{
2016-08-13 15:48:18 +00:00
if($this->response->isUser())
2014-01-27 11:30:39 +00:00
{
2016-08-13 15:48:18 +00:00
if(empty($this->response->rawDataSource)) $this->response->rawDataSource = $page->rawData;
if(empty($this->response->rawDataEdit)) $this->response->rawDataEdit = $page->rawData;
if(empty($this->response->rawDataEndOfLine)) $this->response->rawDataEndOfLine = $this->response->getEndOfLine($page->rawData);
if($page->statusCode==434) $this->response->rawDataEdit = $this->response->getRawDataNew($page->location);
2014-01-27 11:30:39 +00:00
}
2016-08-13 15:48:18 +00:00
if(empty($this->response->language)) $this->response->language = $page->get("language");
if(empty($this->response->action)) $this->response->action = $this->response->isUser() ? "none" : "login";
if(empty($this->response->status)) $this->response->status = "none";
if($this->response->status=="error") $this->response->action = "error";
2014-01-27 11:30:39 +00:00
}
}
2015-05-26 08:27:28 +00:00
// Handle page content parsing of custom block
2015-06-10 15:13:17 +00:00
function onParseContentBlock($page, $name, $text, $shortcut)
2015-05-26 08:27:28 +00:00
{
2016-07-19 22:12:05 +00:00
$output = null;
2015-06-10 15:13:17 +00:00
if($name=="edit" && $shortcut)
2015-05-26 08:27:28 +00:00
{
$editText = "$name $text";
if(substru($text, 0, 2)=="- ") $editText = trim(substru($text, 2));
$output = "<a href=\"".$page->get("pageEdit")."\">".htmlspecialchars($editText)."</a>";
}
return $output;
}
2015-04-29 07:26:48 +00:00
// Handle page extra HTML data
2015-05-04 11:11:33 +00:00
function onExtra($name)
2013-04-14 22:41:04 +00:00
{
2016-07-19 22:12:05 +00:00
$output = null;
2016-08-13 15:48:18 +00:00
if($name=="header" && $this->response->isActive())
2013-04-14 22:41:04 +00:00
{
2017-02-17 13:52:55 +00:00
$pluginLocation = $this->yellow->config->get("serverBase").$this->yellow->config->get("pluginLocation");
$output = "<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"{$pluginLocation}edit.css\" />\n";
$output .= "<script type=\"text/javascript\" src=\"{$pluginLocation}edit.js\"></script>\n";
2016-04-12 13:58:56 +00:00
$output .= "<script type=\"text/javascript\">\n";
$output .= "// <![CDATA[\n";
2016-08-13 15:48:18 +00:00
$output .= "yellow.page = ".json_encode($this->response->getPageData()).";\n";
$output .= "yellow.config = ".json_encode($this->response->getConfigData()).";\n";
$output .= "yellow.text = ".json_encode($this->response->getTextData()).";\n";
2016-04-12 13:58:56 +00:00
$output .= "// ]]>\n";
$output .= "</script>\n";
2013-04-14 22:41:04 +00:00
}
2015-04-29 07:26:48 +00:00
return $output;
2013-12-21 13:10:15 +00:00
}
// Handle command
function onCommand($args)
{
2016-06-27 13:28:10 +00:00
list($command) = $args;
2013-12-21 13:10:15 +00:00
switch($command)
{
2016-06-02 15:31:42 +00:00
case "clean": $statusCode = $this->cleanCommand($args); break;
2013-12-21 13:10:15 +00:00
case "user": $statusCode = $this->userCommand($args); break;
default: $statusCode = 0;
}
return $statusCode;
}
2015-04-29 07:26:48 +00:00
// Handle command help
function onCommandHelp()
{
2016-07-03 21:13:24 +00:00
return "user [EMAIL PASSWORD NAME LANGUAGE]\n";
2015-04-29 07:26:48 +00:00
}
2016-06-02 15:31:42 +00:00
// Clean user accounts
function cleanCommand($args)
{
2016-06-27 13:28:10 +00:00
$statusCode = 0;
2016-07-15 16:35:11 +00:00
list($command, $path) = $args;
2016-07-19 22:12:05 +00:00
if($path=="all")
2016-07-15 16:35:11 +00:00
{
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
2017-11-04 16:11:34 +00:00
if(!$this->users->clean($fileNameUser))
{
$statusCode = 500;
echo "ERROR cleaning configuration: Can't write file '$fileNameUser'!\n";
}
2016-07-15 16:35:11 +00:00
}
2016-07-03 21:13:24 +00:00
return $statusCode;
2016-06-02 15:31:42 +00:00
}
2015-04-29 07:26:48 +00:00
2015-08-09 20:17:17 +00:00
// Update user account
2013-12-21 13:10:15 +00:00
function userCommand($args)
{
$statusCode = 0;
2016-07-03 21:13:24 +00:00
list($command, $email, $password, $name, $language) = $args;
2015-10-06 12:19:11 +00:00
if(!empty($email) && !empty($password))
{
2016-04-12 13:58:56 +00:00
$userExisting = $this->users->isExisting($email);
$status = $this->getUserAccount($email, $password, $command);
switch($status)
{
2016-04-12 13:58:56 +00:00
case "invalid": echo "ERROR updating configuration: Please enter a valid email!\n"; break;
case "weak": echo "ERROR updating configuration: Please enter a different password!\n"; break;
}
2016-07-19 22:12:05 +00:00
if($status=="ok")
2016-04-12 13:58:56 +00:00
{
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
2016-07-03 21:13:24 +00:00
$status = $this->users->update($fileNameUser, $email, $password, $name, $language, "active") ? "ok" : "error";
2016-07-19 22:12:05 +00:00
if($status=="error") echo "ERROR updating configuration: Can't write file '$fileNameUser'!\n";
2016-04-12 13:58:56 +00:00
}
2016-07-19 22:12:05 +00:00
if($status=="ok")
2016-04-12 13:58:56 +00:00
{
$algorithm = $this->yellow->config->get("editUserHashAlgorithm");
2016-04-12 13:58:56 +00:00
$status = substru($this->users->getHash($email), 0, 5)!="error-hash" ? "ok" : "error";
2016-07-19 22:12:05 +00:00
if($status=="error") echo "ERROR updating configuration: Hash algorithm '$algorithm' not supported!\n";
2016-04-12 13:58:56 +00:00
}
$statusCode = $status=="ok" ? 200 : 500;
2015-10-06 12:19:11 +00:00
echo "Yellow $command: User account ".($statusCode!=200 ? "not " : "");
2016-04-12 13:58:56 +00:00
echo ($userExisting ? "updated" : "created")."\n";
2013-12-21 13:10:15 +00:00
} else {
2015-10-06 12:19:11 +00:00
$statusCode = 200;
2016-08-13 15:48:18 +00:00
foreach($this->users->getData() as $line) echo "$line\n";
2015-10-06 12:19:11 +00:00
if(!$this->users->getNumber()) echo "Yellow $command: No user accounts\n";
2013-12-21 13:10:15 +00:00
}
return $statusCode;
}
2014-07-25 10:46:58 +00:00
// Process request
2017-02-17 13:52:55 +00:00
function processRequest($scheme, $address, $base, $location, $fileName)
2014-07-25 10:46:58 +00:00
{
$statusCode = 0;
if($this->checkUserAuth($scheme, $address, $base, $location, $fileName))
2014-07-25 10:46:58 +00:00
{
2016-04-12 13:58:56 +00:00
switch($_REQUEST["action"])
{
2017-02-17 13:52:55 +00:00
case "": $statusCode = $this->processRequestShow($scheme, $address, $base, $location, $fileName); break;
case "login": $statusCode = $this->processRequestLogin($scheme, $address, $base, $location, $fileName); break;
case "logout": $statusCode = $this->processRequestLogout($scheme, $address, $base, $location, $fileName); break;
case "settings": $statusCode = $this->processRequestSettings($scheme, $address, $base, $location, $fileName); break;
case "version": $statusCode = $this->processRequestVersion($scheme, $address, $base, $location, $fileName); break;
case "update": $statusCode = $this->processRequestUpdate($scheme, $address, $base, $location, $fileName); break;
case "create": $statusCode = $this->processRequestCreate($scheme, $address, $base, $location, $fileName); break;
case "edit": $statusCode = $this->processRequestEdit($scheme, $address, $base, $location, $fileName); break;
case "delete": $statusCode = $this->processRequestDelete($scheme, $address, $base, $location, $fileName); break;
case "preview": $statusCode = $this->processRequestPreview($scheme, $address, $base, $location, $fileName); break;
2018-04-29 15:48:46 +00:00
case "upload": $statusCode = $this->processRequestUpload($scheme, $address, $base, $location, $fileName); break;
2016-04-12 13:58:56 +00:00
}
} else if($this->checkUserUnauth($scheme, $address, $base, $location, $fileName)) {
2017-02-17 13:52:55 +00:00
$this->yellow->lookup->requestHandler = "core";
2016-04-12 13:58:56 +00:00
switch($_REQUEST["action"])
2014-07-25 10:46:58 +00:00
{
2017-02-17 13:52:55 +00:00
case "": $statusCode = $this->processRequestShow($scheme, $address, $base, $location, $fileName); break;
case "signup": $statusCode = $this->processRequestSignup($scheme, $address, $base, $location, $fileName); break;
case "forgot": $statusCode = $this->processRequestForgot($scheme, $address, $base, $location, $fileName); break;
2017-02-17 13:52:55 +00:00
case "confirm": $statusCode = $this->processRequestConfirm($scheme, $address, $base, $location, $fileName); break;
case "approve": $statusCode = $this->processRequestApprove($scheme, $address, $base, $location, $fileName); break;
case "recover": $statusCode = $this->processRequestRecover($scheme, $address, $base, $location, $fileName); break;
case "reactivate": $statusCode = $this->processRequestReactivate($scheme, $address, $base, $location, $fileName); break;
case "verify": $statusCode = $this->processRequestVerify($scheme, $address, $base, $location, $fileName); break;
2017-02-17 13:52:55 +00:00
case "change": $statusCode = $this->processRequestChange($scheme, $address, $base, $location, $fileName); break;
2014-07-25 10:46:58 +00:00
}
}
$this->checkUserFailed($scheme, $address, $base, $location, $fileName);
2014-07-25 10:46:58 +00:00
return $statusCode;
}
2017-01-05 09:39:42 +00:00
// Process request to show file
2017-02-17 13:52:55 +00:00
function processRequestShow($scheme, $address, $base, $location, $fileName)
2014-07-25 10:46:58 +00:00
{
$statusCode = 0;
if(is_readable($fileName))
{
2017-02-17 13:52:55 +00:00
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2014-07-25 10:46:58 +00:00
} else {
2017-01-03 13:11:44 +00:00
if($this->yellow->lookup->isRedirectLocation($location))
2014-07-25 10:46:58 +00:00
{
2017-01-03 13:11:44 +00:00
$location = $this->yellow->lookup->isFileLocation($location) ? "$location/" : "/".$this->yellow->getRequestLanguage()."/";
2017-02-17 13:52:55 +00:00
$location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
2017-11-04 16:11:34 +00:00
$statusCode = $this->yellow->sendStatus(301, $location);
2014-07-25 10:46:58 +00:00
} else {
$this->yellow->page->error($this->response->isUserRestrictions() ? 404 : 434);
2017-11-04 16:11:34 +00:00
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2014-07-25 10:46:58 +00:00
}
}
return $statusCode;
}
2016-04-12 13:58:56 +00:00
// Process request for user login
2017-02-17 13:52:55 +00:00
function processRequestLogin($scheme, $address, $base, $location, $fileName)
2016-04-12 13:58:56 +00:00
{
2017-07-05 10:25:25 +00:00
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
if($this->users->update($fileNameUser, $this->response->userEmail))
2016-04-12 13:58:56 +00:00
{
2017-07-05 10:25:25 +00:00
$home = $this->users->getHome($this->response->userEmail);
if(substru($location, 0, strlenu($home))==$home)
{
$location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
2017-11-04 16:11:34 +00:00
$statusCode = $this->yellow->sendStatus(303, $location);
2017-07-05 10:25:25 +00:00
} else {
$location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $home);
2017-11-04 16:11:34 +00:00
$statusCode = $this->yellow->sendStatus(302, $location);
2017-07-05 10:25:25 +00:00
}
2016-04-12 13:58:56 +00:00
} else {
2017-11-04 16:11:34 +00:00
$this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2016-04-12 13:58:56 +00:00
}
return $statusCode;
}
// Process request for user logout
2017-02-17 13:52:55 +00:00
function processRequestLogout($scheme, $address, $base, $location, $fileName)
2016-04-12 13:58:56 +00:00
{
2016-08-13 15:48:18 +00:00
$this->response->userEmail = "";
$this->response->destroyCookies($scheme, $address, $base);
2016-04-12 13:58:56 +00:00
$location = $this->yellow->lookup->normaliseUrl(
$this->yellow->config->get("serverScheme"),
2017-02-17 13:52:55 +00:00
$this->yellow->config->get("serverAddress"),
2016-04-12 13:58:56 +00:00
$this->yellow->config->get("serverBase"), $location);
2017-11-04 16:11:34 +00:00
$statusCode = $this->yellow->sendStatus(302, $location);
2016-04-12 13:58:56 +00:00
return $statusCode;
}
// Process request for user signup
2017-02-17 13:52:55 +00:00
function processRequestSignup($scheme, $address, $base, $location, $fileName)
2016-04-12 13:58:56 +00:00
{
2016-08-13 15:48:18 +00:00
$this->response->action = "signup";
$this->response->status = "ok";
2016-04-12 13:58:56 +00:00
$name = trim(preg_replace("/[^\pL\d\-\. ]/u", "-", $_REQUEST["name"]));
$email = trim($_REQUEST["email"]);
$password = trim($_REQUEST["password"]);
$consent = trim($_REQUEST["consent"]);
if(empty($name) || empty($email) || empty($password) || empty($consent)) $this->response->status = "incomplete";
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok") $this->response->status = $this->getUserAccount($email, $password, $this->response->action);
if($this->response->status=="ok" && $this->response->isLoginRestrictions()) $this->response->status = "next";
2016-08-16 08:16:13 +00:00
if($this->response->status=="ok" && $this->users->isTaken($email)) $this->response->status = "next";
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok")
2016-04-12 13:58:56 +00:00
{
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
2016-08-13 15:48:18 +00:00
$this->response->status = $this->users->update($fileNameUser, $email, $password, $name, "", "unconfirmed") ? "ok" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
2016-04-12 13:58:56 +00:00
}
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok")
2016-04-12 13:58:56 +00:00
{
2017-02-17 13:52:55 +00:00
$this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "confirm") ? "next" : "error";
2016-08-13 15:48:18 +00:00
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
2016-04-12 13:58:56 +00:00
}
2017-02-17 13:52:55 +00:00
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2016-04-12 13:58:56 +00:00
return $statusCode;
}
// Process request to confirm user signup
2017-02-17 13:52:55 +00:00
function processRequestConfirm($scheme, $address, $base, $location, $fileName)
2016-04-12 13:58:56 +00:00
{
2016-08-13 15:48:18 +00:00
$this->response->action = "confirm";
$this->response->status = "ok";
2016-04-12 13:58:56 +00:00
$email = $_REQUEST["email"];
$this->response->status = $this->getUserStatus($email, $_REQUEST["action"]);
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok")
2016-04-12 13:58:56 +00:00
{
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
2016-08-13 15:48:18 +00:00
$this->response->status = $this->users->update($fileNameUser, $email, "", "", "", "unapproved") ? "ok" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
2016-04-12 13:58:56 +00:00
}
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok")
2016-04-12 13:58:56 +00:00
{
2017-02-17 13:52:55 +00:00
$this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "approve") ? "done" : "error";
2016-08-13 15:48:18 +00:00
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
2016-04-12 13:58:56 +00:00
}
2017-02-17 13:52:55 +00:00
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2016-04-12 13:58:56 +00:00
return $statusCode;
}
// Process request to approve user signup
2017-02-17 13:52:55 +00:00
function processRequestApprove($scheme, $address, $base, $location, $fileName)
2016-04-12 13:58:56 +00:00
{
2016-08-13 15:48:18 +00:00
$this->response->action = "approve";
$this->response->status = "ok";
2016-04-12 13:58:56 +00:00
$email = $_REQUEST["email"];
$this->response->status = $this->getUserStatus($email, $_REQUEST["action"]);
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok")
2016-04-12 13:58:56 +00:00
{
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
2016-08-13 15:48:18 +00:00
$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'!");
2016-04-12 13:58:56 +00:00
}
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok")
2016-04-12 13:58:56 +00:00
{
2017-02-17 13:52:55 +00:00
$this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "welcome") ? "done" : "error";
2016-08-13 15:48:18 +00:00
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
2016-04-12 13:58:56 +00:00
}
2017-02-17 13:52:55 +00:00
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2016-04-12 13:58:56 +00:00
return $statusCode;
}
2017-07-05 10:25:25 +00:00
// Process request for forgotten password
function processRequestForgot($scheme, $address, $base, $location, $fileName)
2017-07-05 10:25:25 +00:00
{
$this->response->action = "forgot";
2017-07-05 10:25:25 +00:00
$this->response->status = "ok";
$email = trim($_REQUEST["email"]);
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) $this->response->status = "invalid";
if($this->response->status=="ok" && !$this->users->isExisting($email)) $this->response->status = "next";
2017-07-05 10:25:25 +00:00
if($this->response->status=="ok")
{
$this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "recover") ? "next" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
2017-07-05 10:25:25 +00:00
}
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
return $statusCode;
}
2016-04-12 13:58:56 +00:00
// Process request to recover password
2017-02-17 13:52:55 +00:00
function processRequestRecover($scheme, $address, $base, $location, $fileName)
2016-04-12 13:58:56 +00:00
{
2016-08-13 15:48:18 +00:00
$this->response->action = "recover";
$this->response->status = "ok";
2016-04-12 13:58:56 +00:00
$email = trim($_REQUEST["email"]);
$password = trim($_REQUEST["password"]);
$this->response->status = $this->getUserStatus($email, $_REQUEST["action"]);
if($this->response->status=="ok")
2016-04-12 13:58:56 +00:00
{
if(empty($password)) $this->response->status = "password";
if($this->response->status=="ok") $this->response->status = $this->getUserAccount($email, $password, $this->response->action);
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok")
2016-04-12 13:58:56 +00:00
{
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
$this->response->status = $this->users->update($fileNameUser, $email, $password) ? "ok" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
2016-04-12 13:58:56 +00:00
}
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok")
2016-04-12 13:58:56 +00:00
{
$this->response->userEmail = "";
$this->response->destroyCookies($scheme, $address, $base);
$this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "information") ? "done" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
2016-04-12 13:58:56 +00:00
}
}
2017-02-17 13:52:55 +00:00
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2016-04-12 13:58:56 +00:00
return $statusCode;
}
2016-08-13 15:48:18 +00:00
// Process request to reactivate account
function processRequestReactivate($scheme, $address, $base, $location, $fileName)
{
$this->response->action = "reactivate";
$this->response->status = "ok";
$email = $_REQUEST["email"];
$this->response->status = $this->getUserStatus($email, $_REQUEST["action"]);
if($this->response->status=="ok")
{
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
$this->response->status = $this->users->update($fileNameUser, $email, "", "", "", "active") ? "done" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
}
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
return $statusCode;
}
2016-05-15 16:35:10 +00:00
// Process request to change settings
2017-02-17 13:52:55 +00:00
function processRequestSettings($scheme, $address, $base, $location, $fileName)
2016-05-15 16:35:10 +00:00
{
2016-08-13 15:48:18 +00:00
$this->response->action = "settings";
$this->response->status = "ok";
$email = trim($_REQUEST["email"]);
$emailSource = $this->response->userEmail;
$password = trim($_REQUEST["password"]);
$name = trim(preg_replace("/[^\pL\d\-\. ]/u", "-", $_REQUEST["name"]));
$language = trim($_REQUEST["language"]);
if($email!=$emailSource || !empty($password))
2016-05-15 16:35:10 +00:00
{
2016-08-13 15:48:18 +00:00
if(empty($email)) $this->response->status = "invalid";
if($this->response->status=="ok") $this->response->status = $this->getUserAccount($email, $password, $this->response->action);
2016-08-16 08:16:13 +00:00
if($this->response->status=="ok" && $email!=$emailSource && $this->users->isTaken($email)) $this->response->status = "taken";
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok" && $email!=$emailSource)
{
$pending = $emailSource;
2017-07-05 10:25:25 +00:00
$home = $this->users->getHome($emailSource);
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
$this->response->status = $this->users->update($fileNameUser, $email, "no", $name, $language, "unverified", "", "", "", $pending, $home) ? "ok" : "error";
2016-08-13 15:48:18 +00:00
if($this->response->status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
}
if($this->response->status=="ok")
{
$pending = $email.':'.(empty($password) ? $this->users->getHash($emailSource) : $this->users->createHash($password));
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
$this->response->status = $this->users->update($fileNameUser, $emailSource, "", $name, $language, "", "", "", "", $pending) ? "ok" : "error";
2016-08-13 15:48:18 +00:00
if($this->response->status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
}
if($this->response->status=="ok")
{
$action = $email!=$emailSource ? "verify" : "change";
2017-02-17 13:52:55 +00:00
$this->response->status = $this->response->sendMail($scheme, $address, $base, $email, $action) ? "next" : "error";
2016-08-13 15:48:18 +00:00
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
} else {
if($this->response->status=="ok")
{
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
2016-08-13 15:48:18 +00:00
$this->response->status = $this->users->update($fileNameUser, $email, "", $name, $language) ? "done" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
}
2016-06-02 15:31:42 +00:00
}
2016-08-13 15:48:18 +00:00
if($this->response->status=="done")
2016-06-02 15:31:42 +00:00
{
2017-02-17 13:52:55 +00:00
$location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
2017-11-04 16:11:34 +00:00
$statusCode = $this->yellow->sendStatus(303, $location);
2016-06-02 15:31:42 +00:00
} else {
2017-02-17 13:52:55 +00:00
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2016-05-15 16:35:10 +00:00
}
return $statusCode;
}
2016-08-13 15:48:18 +00:00
// Process request to verify email
function processRequestVerify($scheme, $address, $base, $location, $fileName)
2016-08-13 15:48:18 +00:00
{
$this->response->action = "verify";
2016-08-13 15:48:18 +00:00
$this->response->status = "ok";
$email = $emailSource = $_REQUEST["email"];
$this->response->status = $this->getUserStatus($email, $_REQUEST["action"]);
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok")
{
$emailSource = $this->users->getPending($email);
2016-08-16 08:16:13 +00:00
if($this->users->getStatus($emailSource)!="active") $this->response->status = "done";
2016-08-13 15:48:18 +00:00
}
if($this->response->status=="ok")
{
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
2016-08-13 15:48:18 +00:00
$this->response->status = $this->users->update($fileNameUser, $email, "", "", "", "unchanged") ? "ok" : "error";
if($this->response->status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
}
if($this->response->status=="ok")
{
2017-02-17 13:52:55 +00:00
$this->response->status = $this->response->sendMail($scheme, $address, $base, $emailSource, "change") ? "done" : "error";
2016-08-13 15:48:18 +00:00
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
2017-02-17 13:52:55 +00:00
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2016-08-13 15:48:18 +00:00
return $statusCode;
}
// Process request to change email or password
2017-02-17 13:52:55 +00:00
function processRequestChange($scheme, $address, $base, $location, $fileName)
2016-08-13 15:48:18 +00:00
{
$this->response->action = "change";
$this->response->status = "ok";
$email = $emailSource = trim($_REQUEST["email"]);
$this->response->status = $this->getUserStatus($email, $_REQUEST["action"]);
2016-08-13 15:48:18 +00:00
if($this->response->status=="ok")
{
list($email, $hash) = explode(':', $this->users->getPending($email), 2);
if(!$this->users->isExisting($email) || empty($hash)) $this->response->status = "done";
}
if($this->response->status=="ok" && $email!=$emailSource)
{
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
2017-01-03 13:11:44 +00:00
$this->users->users[$emailSource]["pending"] = "none";
$this->response->status = $this->users->update($fileNameUser, $emailSource, "", "", "", "removed") ? "ok" : "error";
2016-08-13 15:48:18 +00:00
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;
2017-01-03 13:11:44 +00:00
$this->users->users[$email]["pending"] = "none";
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
2016-08-13 15:48:18 +00:00
$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'!");
}
if($this->response->status=="ok")
{
$this->response->userEmail = "";
$this->response->destroyCookies($scheme, $address, $base);
2017-02-17 13:52:55 +00:00
$this->response->status = $this->response->sendMail($scheme, $address, $base, $email, "information") ? "done" : "error";
2016-08-13 15:48:18 +00:00
if($this->response->status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
2017-02-17 13:52:55 +00:00
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2016-08-13 15:48:18 +00:00
return $statusCode;
}
2016-04-12 13:58:56 +00:00
2016-08-18 19:57:07 +00:00
// Process request to show software version
2017-02-17 13:52:55 +00:00
function processRequestVersion($scheme, $address, $base, $location, $fileName)
2016-08-16 08:16:13 +00:00
{
$this->response->action = "version";
$this->response->status = "ok";
if($this->yellow->plugins->isExisting("update"))
{
2017-02-17 13:52:55 +00:00
list($statusCodeCurrent, $dataCurrent) = $this->yellow->plugins->get("update")->getSoftwareVersion();
list($statusCodeLatest, $dataLatest) = $this->yellow->plugins->get("update")->getSoftwareVersion(true);
list($statusCodeModified, $dataModified) = $this->yellow->plugins->get("update")->getSoftwareModified();
$statusCode = max($statusCodeCurrent, $statusCodeLatest, $statusCodeModified);
if($this->response->isUserWebmaster())
2016-08-16 08:16:13 +00:00
{
2017-02-17 13:52:55 +00:00
foreach($dataCurrent as $key=>$value)
2016-08-16 08:16:13 +00:00
{
2017-02-17 13:52:55 +00:00
if(strnatcasecmp($dataCurrent[$key], $dataLatest[$key])<0)
{
++$updates;
if(!empty($this->response->rawDataOutput)) $this->response->rawDataOutput .= "<br />\n";
$this->response->rawDataOutput .= htmlspecialchars("$key $dataLatest[$key]");
}
}
if($updates==0)
{
foreach($dataCurrent as $key=>$value)
{
if(!is_null($dataModified[$key]) && !is_null($dataLatest[$key]))
{
2017-11-04 16:11:34 +00:00
$rawData = $this->yellow->text->getTextHtml("editVersionUpdateModified", $this->response->language)." - <a href=\"#\" data-action=\"update\" data-status=\"update\" data-args=\"".$this->yellow->toolbox->normaliseArgs("option:force/feature:$key")."\">".$this->yellow->text->getTextHtml("editVersionUpdateForce", $this->response->language)."</a>";
2017-02-17 13:52:55 +00:00
$rawData = preg_replace("/@software/i", htmlspecialchars("$key $dataLatest[$key]"), $rawData);
if(!empty($this->response->rawDataOutput)) $this->response->rawDataOutput .= "<br />\n";
$this->response->rawDataOutput .= $rawData;
}
}
}
} else {
foreach($dataCurrent as $key=>$value)
{
if(strnatcasecmp($dataCurrent[$key], $dataLatest[$key])<0) ++$updates;
2016-08-16 08:16:13 +00:00
}
}
2017-01-03 13:11:44 +00:00
$this->response->status = $updates ? "updates" : "done";
if($statusCode!=200) $this->response->status = "error";
2016-08-16 08:16:13 +00:00
}
2017-02-17 13:52:55 +00:00
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2016-08-16 08:16:13 +00:00
return $statusCode;
}
2016-08-18 19:57:07 +00:00
// Process request to update website
2017-02-17 13:52:55 +00:00
function processRequestUpdate($scheme, $address, $base, $location, $fileName)
2016-08-16 08:16:13 +00:00
{
$statusCode = 0;
2017-01-03 13:11:44 +00:00
if($this->yellow->plugins->isExisting("update") && $this->response->isUserWebmaster())
2016-08-16 08:16:13 +00:00
{
2017-02-17 13:52:55 +00:00
$option = trim($_REQUEST["option"]);
$feature = trim($_REQUEST["feature"]);
$statusCode = $this->yellow->command("update", $option, $feature);
2016-08-16 08:16:13 +00:00
if($statusCode==200)
{
2017-02-17 13:52:55 +00:00
$location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
2017-11-04 16:11:34 +00:00
$statusCode = $this->yellow->sendStatus(303, $location);
2016-08-16 08:16:13 +00:00
}
}
return $statusCode;
}
2014-07-25 10:46:58 +00:00
// Process request to create page
2017-02-17 13:52:55 +00:00
function processRequestCreate($scheme, $address, $base, $location, $fileName)
2014-07-25 10:46:58 +00:00
{
$statusCode = 0;
2017-11-04 16:11:34 +00:00
if(!$this->response->isUserRestrictions() && !empty($_REQUEST["rawdataedit"]))
2014-07-25 10:46:58 +00:00
{
$this->response->rawDataSource = $_REQUEST["rawdatasource"];
$this->response->rawDataEdit = $_REQUEST["rawdatasource"];
$this->response->rawDataEndOfLine = $_REQUEST["rawdataendofline"];
$rawData = $_REQUEST["rawdataedit"];
$page = $this->response->getPageNew($scheme, $address, $base, $location, $fileName, $rawData, $this->response->getEndOfLine());
if(!$page->isError())
2014-07-25 10:46:58 +00:00
{
2016-08-13 15:48:18 +00:00
if($this->yellow->toolbox->createFile($page->fileName, $page->rawData, true))
{
2017-02-17 13:52:55 +00:00
$location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $page->location);
2017-11-04 16:11:34 +00:00
$statusCode = $this->yellow->sendStatus(303, $location);
} else {
2017-11-04 16:11:34 +00:00
$this->yellow->page->error(500, "Can't write file '$page->fileName'!");
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
}
2014-07-25 10:46:58 +00:00
} else {
2017-11-04 16:11:34 +00:00
$this->yellow->page->error(500, $page->get("pageError"));
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2014-07-25 10:46:58 +00:00
}
}
return $statusCode;
}
// Process request to edit page
2017-02-17 13:52:55 +00:00
function processRequestEdit($scheme, $address, $base, $location, $fileName)
2014-07-25 10:46:58 +00:00
{
$statusCode = 0;
2017-11-04 16:11:34 +00:00
if(!$this->response->isUserRestrictions() && !empty($_REQUEST["rawdataedit"]))
2014-07-25 10:46:58 +00:00
{
$this->response->rawDataSource = $_REQUEST["rawdatasource"];
$this->response->rawDataEdit = $_REQUEST["rawdataedit"];
$this->response->rawDataEndOfLine = $_REQUEST["rawdataendofline"];
$rawDataFile = $this->yellow->toolbox->readFile($fileName);
$page = $this->response->getPageEdit($scheme, $address, $base, $location, $fileName,
$this->response->rawDataSource, $this->response->rawDataEdit, $rawDataFile, $this->response->rawDataEndOfLine);
if(!$page->isError())
2014-07-25 10:46:58 +00:00
{
if($this->yellow->toolbox->renameFile($fileName, $page->fileName, true) &&
$this->yellow->toolbox->createFile($page->fileName, $page->rawData))
2014-07-25 10:46:58 +00:00
{
2017-02-17 13:52:55 +00:00
$location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $page->location);
2017-11-04 16:11:34 +00:00
$statusCode = $this->yellow->sendStatus(303, $location);
2014-07-25 10:46:58 +00:00
} else {
2017-11-04 16:11:34 +00:00
$this->yellow->page->error(500, "Can't write file '$page->fileName'!");
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2014-07-25 10:46:58 +00:00
}
} else {
2017-11-04 16:11:34 +00:00
$this->yellow->page->error(500, $page->get("pageError"));
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2014-07-25 10:46:58 +00:00
}
}
return $statusCode;
}
// Process request to delete page
2017-02-17 13:52:55 +00:00
function processRequestDelete($scheme, $address, $base, $location, $fileName)
2013-04-14 22:41:04 +00:00
{
$statusCode = 0;
2016-08-13 15:48:18 +00:00
if(!$this->response->isUserRestrictions() && is_file($fileName))
2013-04-14 22:41:04 +00:00
{
$this->response->rawDataSource = $_REQUEST["rawdatasource"];
$this->response->rawDataEdit = $_REQUEST["rawdatasource"];
$this->response->rawDataEndOfLine = $_REQUEST["rawdataendofline"];
$rawDataFile = $this->yellow->toolbox->readFile($fileName);
$page = $this->response->getPageDelete($scheme, $address, $base, $location, $fileName,
$rawDataFile, $this->response->rawDataEndOfLine);
if(!$page->isError())
2014-07-25 10:46:58 +00:00
{
if($this->yellow->lookup->isFileLocation($location))
2016-08-13 15:48:18 +00:00
{
if($this->yellow->toolbox->deleteFile($fileName, $this->yellow->config->get("trashDir")))
{
$location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
2017-11-04 16:11:34 +00:00
$statusCode = $this->yellow->sendStatus(303, $location);
} else {
2017-11-04 16:11:34 +00:00
$this->yellow->page->error(500, "Can't delete file '$fileName'!");
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
}
2016-08-13 15:48:18 +00:00
} else {
if($this->yellow->toolbox->deleteDirectory(dirname($fileName), $this->yellow->config->get("trashDir")))
{
$location = $this->yellow->lookup->normaliseUrl($scheme, $address, $base, $location);
2017-11-04 16:11:34 +00:00
$statusCode = $this->yellow->sendStatus(303, $location);
} else {
2017-11-04 16:11:34 +00:00
$this->yellow->page->error(500, "Can't delete file '$fileName'!");
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
}
2016-08-13 15:48:18 +00:00
}
2014-07-25 10:46:58 +00:00
} else {
2017-11-04 16:11:34 +00:00
$this->yellow->page->error(500, $page->get("pageError"));
$statusCode = $this->yellow->processRequest($scheme, $address, $base, $location, $fileName, false);
2014-07-25 10:46:58 +00:00
}
2013-04-14 22:41:04 +00:00
}
return $statusCode;
}
// Process request to show preview
function processRequestPreview($scheme, $address, $base, $location, $fileName)
{
$page = $this->response->getPagePreview($scheme, $address, $base, $location, $fileName,
$_REQUEST["rawdataedit"], $_REQUEST["rawdataendofline"]);
$statusCode = $this->yellow->sendData(200, $page->outputData, "", false);
if(defined("DEBUG") && DEBUG>=1)
{
$parser = $page->get("parser");
echo "YellowEdit::processRequestPreview parser:$parser<br/>\n";
}
return $statusCode;
}
2017-07-05 10:25:25 +00:00
2018-04-29 15:48:46 +00:00
// Process request to upload file
function processRequestUpload($scheme, $address, $base, $location, $fileName)
{
$data = array();
$fileNameTemp = $_FILES["file"]["tmp_name"];
$fileNameShort = preg_replace("/[^\pL\d\-\.]/u", "-", basename($_FILES["file"]["name"]));
$fileSizeMax = $this->yellow->toolbox->getNumberBytes(ini_get("upload_max_filesize"));
$extension = strtoloweru(($pos = strrposu($fileNameShort, '.')) ? substru($fileNameShort, $pos) : "");
$extensions = preg_split("/\s*,\s*/", $this->yellow->config->get("editUploadExtensions"));
if(!$this->response->isUserRestrictions() && is_uploaded_file($fileNameTemp) &&
filesize($fileNameTemp)<=$fileSizeMax && in_array($extension, $extensions))
{
$file = $this->response->getFileUpload($scheme, $address, $base, $location, $fileNameTemp, $fileNameShort);
if(!$file->isError() && $this->yellow->toolbox->renameFile($fileNameTemp, $file->fileName, true))
{
$data["location"] = $file->getLocation();
} else {
$data["error"] = "Can't write file '$file->fileName'!";
}
} else {
$data["error"] = "Can't write file '$fileNameShort'!";
}
$statusCode = $this->yellow->sendData(is_null($data["error"]) ? 200 : 500, json_encode($data), "a.json", false);
return $statusCode;
}
// Check request
2016-06-02 15:31:42 +00:00
function checkRequest($location)
2013-04-14 22:41:04 +00:00
{
$locationLength = strlenu($this->yellow->config->get("editLocation"));
$this->response->active = substru($location, 0, $locationLength)==$this->yellow->config->get("editLocation");
2016-08-13 15:48:18 +00:00
return $this->response->isActive();
2013-04-14 22:41:04 +00:00
}
// Check user authentication
function checkUserAuth($scheme, $address, $base, $location, $fileName)
2013-04-14 22:41:04 +00:00
{
if($this->isRequestSameSite("POST", $scheme, $address) || $_REQUEST["action"]=="")
2013-04-14 22:41:04 +00:00
{
if($_REQUEST["action"]=="login")
2013-04-14 22:41:04 +00:00
{
$email = $_REQUEST["email"];
$password = $_REQUEST["password"];
if($this->users->checkAuthLogin($email, $password))
{
$this->response->createCookies($scheme, $address, $base, $email);
$this->response->userEmail = $email;
$this->response->userRestrictions = $this->getUserRestrictions($email, $location, $fileName);
$this->response->language = $this->getUserLanguage($email);
} else {
$this->response->userFailedError = "login";
$this->response->userFailedEmail = $email;
$this->response->userFailedExpire = PHP_INT_MAX;
}
} else if(isset($_COOKIE["authtoken"]) && isset($_COOKIE["csrftoken"])) {
if($this->users->checkAuthToken($_COOKIE["authtoken"], $_COOKIE["csrftoken"], $_POST["csrftoken"], $_REQUEST["action"]==""))
{
$this->response->userEmail = $email = $this->users->getAuthEmail($_COOKIE["authtoken"]);
$this->response->userRestrictions = $this->getUserRestrictions($email, $location, $fileName);
$this->response->language = $this->getUserLanguage($email);
} else {
$this->response->userFailedError = "auth";
$this->response->userFailedEmail = $this->users->getAuthEmail($_COOKIE["authtoken"]);
$this->response->userFailedExpire = $this->users->getAuthExpire($_COOKIE["authtoken"]);
}
2013-04-14 22:41:04 +00:00
}
}
2016-08-13 15:48:18 +00:00
return $this->response->isUser();
2016-04-12 13:58:56 +00:00
}
// Check user without authentication
function checkUserUnauth($scheme, $address, $base, $location, $fileName)
{
$ok = false;
if($_REQUEST["action"]=="" || $_REQUEST["action"]=="signup" || $_REQUEST["action"]=="forgot")
{
$ok = true;
} else if(isset($_REQUEST["actiontoken"])) {
if($this->users->checkActionToken($_REQUEST["actiontoken"], $_REQUEST["email"], $_REQUEST["action"], $_REQUEST["expire"]))
{
$ok = true;
} else {
$this->response->userFailedError = "action";
$this->response->userFailedEmail = $_REQUEST["email"];
$this->response->userFailedExpire = $_REQUEST["expire"];
}
}
return $ok;
}
2017-11-04 16:11:34 +00:00
// Check user failed
function checkUserFailed($scheme, $address, $base, $location, $fileName)
{
if(!empty($this->response->userFailedError))
2017-11-04 16:11:34 +00:00
{
if($this->response->userFailedExpire>time() && $this->users->isExisting($this->response->userFailedEmail))
2017-11-04 16:11:34 +00:00
{
$email = $this->response->userFailedEmail;
2017-11-04 16:11:34 +00:00
$modified = $this->users->getModified($email);
$errors = $this->users->getErrors($email)+1;
$fileNameUser = $this->yellow->config->get("configDir").$this->yellow->config->get("editUserFile");
$status = $this->users->update($fileNameUser, $email, "", "", "", "", "", $modified, $errors) ? "ok" : "error";
2017-11-04 16:11:34 +00:00
if($status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
if($errors==$this->yellow->config->get("editBruteForceProtection"))
{
$statusBeforeProtection = $this->users->getStatus($email);
$statusAfterProtection = ($statusBeforeProtection=="active" || $statusBeforeProtection=="inactive") ? "inactive" : "removed";
2017-11-04 16:11:34 +00:00
if($status=="ok")
{
$status = $this->users->update($fileNameUser, $email, "", "", "", $statusAfterProtection, "", $modified, $errors) ? "ok" : "error";
2017-11-04 16:11:34 +00:00
if($status=="error") $this->yellow->page->error(500, "Can't write file '$fileNameUser'!");
}
if($status=="ok" && $statusBeforeProtection=="active")
2017-11-04 16:11:34 +00:00
{
$status = $this->response->sendMail($scheme, $address, $base, $email, "reactivate") ? "done" : "error";
if($status=="error") $this->yellow->page->error(500, "Can't send email on this server!");
}
}
}
if($this->response->userFailedError=="login" || $this->response->userFailedError=="auth")
{
$this->response->destroyCookies($scheme, $address, $base);
$this->response->status = "error";
$this->yellow->page->error(430);
} else {
$this->response->status = "error";
$this->yellow->page->error(500, "Link has expired!");
}
2017-11-04 16:11:34 +00:00
}
}
// Return user status changes
function getUserStatus($email, $action)
{
switch($action)
{
case "confirm": $statusExpected = "unconfirmed"; break;
case "approve": $statusExpected = "unapproved"; break;
case "recover": $statusExpected = "active"; break;
case "reactivate": $statusExpected = "inactive"; break;
case "verify": $statusExpected = "unverified"; break;
case "change": $statusExpected = "active"; break;
}
return $this->users->getStatus($email)==$statusExpected ? "ok" : "done";
}
2016-04-12 13:58:56 +00:00
// Return user account changes
function getUserAccount($email, $password, $action)
{
2016-07-19 22:12:05 +00:00
$status = null;
foreach($this->yellow->plugins->plugins as $key=>$value)
{
if(method_exists($value["obj"], "onEditUserAccount"))
{
$status = $value["obj"]->onEditUserAccount($email, $password, $action, $this->users);
2016-05-15 16:35:10 +00:00
if(!is_null($status)) break;
}
}
2016-05-15 16:35:10 +00:00
if(is_null($status))
2015-09-06 15:59:14 +00:00
{
2016-05-15 16:35:10 +00:00
$status = "ok";
if(!empty($password) && strlenu($password)<$this->yellow->config->get("editUserPasswordMinLength")) $status = "weak";
2016-05-15 16:35:10 +00:00
if(!empty($email) && !filter_var($email, FILTER_VALIDATE_EMAIL)) $status = "invalid";
2015-09-06 15:59:14 +00:00
}
2016-05-15 16:35:10 +00:00
return $status;
2013-04-14 22:41:04 +00:00
}
// Return user restrictions
2016-04-12 13:58:56 +00:00
function getUserRestrictions($email, $location, $fileName)
2015-08-09 20:17:17 +00:00
{
2016-07-19 22:12:05 +00:00
$userRestrictions = null;
2016-04-12 13:58:56 +00:00
foreach($this->yellow->plugins->plugins as $key=>$value)
2015-10-06 12:19:11 +00:00
{
if(method_exists($value["obj"], "onEditUserRestrictions"))
2016-04-12 13:58:56 +00:00
{
$userRestrictions = $value["obj"]->onEditUserRestrictions($email, $location, $fileName, $this->users);
2016-04-12 13:58:56 +00:00
if(!is_null($userRestrictions)) break;
}
2015-10-06 12:19:11 +00:00
}
2016-04-12 13:58:56 +00:00
if(is_null($userRestrictions))
{
2016-08-13 15:48:18 +00:00
$userRestrictions = substru($location, 0, strlenu($this->users->getHome($email)))!=$this->users->getHome($email);
$userRestrictions |= empty($fileName) || strlenu(dirname($fileName))>128 || strlenu(basename($fileName))>128;
2016-04-12 13:58:56 +00:00
}
return $userRestrictions;
2015-08-09 20:17:17 +00:00
}
// Return user language
function getUserLanguage($email)
{
$language = $this->users->getLanguage($email);
if(!$this->yellow->text->isLanguage($language)) $language = $this->yellow->config->get("language");
return $language;
}
// Check if request came from same site
function isRequestSameSite($method, $scheme, $address)
{
if(preg_match("#^(\w+)://([^/]+)(.*)$#", $_SERVER["HTTP_REFERER"], $matches)) $origin = "$matches[1]://$matches[2]";
if(isset($_SERVER["HTTP_ORIGIN"])) $origin = $_SERVER["HTTP_ORIGIN"];
return $_SERVER["REQUEST_METHOD"]==$method && $origin=="$scheme://$address";
}
2016-08-13 15:48:18 +00:00
}
2015-08-09 20:17:17 +00:00
2016-08-13 15:48:18 +00:00
class YellowResponse
{
var $yellow; //access to API
var $plugin; //access to plugin
var $active; //location is active? (boolean)
2016-08-13 15:48:18 +00:00
var $userEmail; //user email
var $userRestrictions; //user can change page? (boolean)
var $userFailedError; //error of failed authentication
var $userFailedEmail; //email of failed authentication
var $userFailedExpire; //expiration time of failed authentication
2016-08-13 15:48:18 +00:00
var $rawDataSource; //raw data of page for comparison
var $rawDataEdit; //raw data of page for editing
2016-08-16 08:16:13 +00:00
var $rawDataOutput; //raw data of dynamic output
var $rawDataEndOfLine; //end of line format for raw data
var $language; //response language
2016-08-13 15:48:18 +00:00
var $action; //response action
var $status; //response status
2014-07-25 10:46:58 +00:00
2016-08-13 15:48:18 +00:00
function __construct($yellow)
2015-05-24 15:31:17 +00:00
{
2016-08-13 15:48:18 +00:00
$this->yellow = $yellow;
$this->plugin = $yellow->plugins->get("edit");
2015-05-24 15:31:17 +00:00
}
2014-07-25 10:46:58 +00:00
// Return new page
function getPageNew($scheme, $address, $base, $location, $fileName, $rawData, $endOfLine)
2014-07-25 10:46:58 +00:00
{
2015-01-19 19:05:51 +00:00
$page = new YellowPage($this->yellow);
2017-02-17 13:52:55 +00:00
$page->setRequestInformation($scheme, $address, $base, $location, $fileName);
$page->parseData($this->normaliseLines($rawData, $endOfLine), false, 0);
$this->editContentFile($page, "create");
if($this->yellow->lookup->isFileLocation($location) || $this->yellow->pages->find($page->location))
2014-07-25 10:46:58 +00:00
{
2018-04-29 15:48:46 +00:00
$page->location = $this->getPageNewLocation($page->rawData, $page->location, $page->get("pageNewLocation"));
$page->fileName = $this->yellow->lookup->findFileNew($page->location, $page->get("published"));
while($this->yellow->pages->find($page->location) || empty($page->fileName))
2014-07-25 10:46:58 +00:00
{
$rawData = $this->yellow->toolbox->setMetaData($page->rawData, "title", $this->getTitleNext($page->rawData));
$page->rawData = $this->normaliseLines($rawData, $endOfLine);
2018-04-29 15:48:46 +00:00
$page->location = $this->getPageNewLocation($page->rawData, $page->location, $page->get("pageNewLocation"));
$page->fileName = $this->yellow->lookup->findFileNew($page->location, $page->get("published"));
if(++$pageCounter>999) break;
2014-07-25 10:46:58 +00:00
}
if($this->yellow->pages->find($page->location) || empty($page->fileName))
{
$page->error(500, "Page '".$page->get("title")."' is not possible!");
}
} else {
$page->fileName = $this->yellow->lookup->findFileNew($page->location);
}
if($this->plugin->getUserRestrictions($this->userEmail, $page->location, $page->fileName))
2016-04-12 13:58:56 +00:00
{
$page->error(500, "Page '".$page->get("title")."' is restricted!");
2016-04-12 13:58:56 +00:00
}
return $page;
}
// Return modified page
function getPageEdit($scheme, $address, $base, $location, $fileName, $rawDataSource, $rawDataEdit, $rawDataFile, $endOfLine)
{
2015-01-19 19:05:51 +00:00
$page = new YellowPage($this->yellow);
2017-02-17 13:52:55 +00:00
$page->setRequestInformation($scheme, $address, $base, $location, $fileName);
$rawData = $this->plugin->merge->merge(
$this->normaliseLines($rawDataSource, $endOfLine),
$this->normaliseLines($rawDataEdit, $endOfLine),
$this->normaliseLines($rawDataFile, $endOfLine));
$page->parseData($this->normaliseLines($rawData, $endOfLine), false, 0);
$this->editContentFile($page, "edit");
if(empty($page->rawData)) $page->error(500, "Page has been modified by someone else!");
2015-04-29 07:26:48 +00:00
if($this->yellow->lookup->isFileLocation($location) && !$page->isError())
{
2015-01-19 19:05:51 +00:00
$pageSource = new YellowPage($this->yellow);
2017-02-17 13:52:55 +00:00
$pageSource->setRequestInformation($scheme, $address, $base, $location, $fileName);
$pageSource->parseData($this->normaliseLines($rawDataSource, $endOfLine), false, 0);
if(substrb($pageSource->rawData, 0, $pageSource->metaDataOffsetBytes) !=
substrb($page->rawData, 0, $page->metaDataOffsetBytes))
2014-07-25 10:46:58 +00:00
{
2018-04-29 15:48:46 +00:00
$page->location = $this->getPageNewLocation($page->rawData, $page->location, $page->get("pageNewLocation"));
$page->fileName = $this->yellow->lookup->findFileNew($page->location, $page->get("published"));
if($page->location!=$pageSource->location)
{
if(!$this->yellow->lookup->isFileLocation($page->location) || empty($page->fileName))
2015-10-21 12:28:56 +00:00
{
$page->error(500, "Page '".$page->get("title")."' is not possible!");
2015-10-21 12:28:56 +00:00
} else if($this->yellow->pages->find($page->location)) {
$page->error(500, "Page '".$page->get("title")."' already exists!");
}
}
2014-07-25 10:46:58 +00:00
}
}
if($this->plugin->getUserRestrictions($this->userEmail, $page->location, $page->fileName))
2016-04-12 13:58:56 +00:00
{
$page->error(500, "Page '".$page->get("title")."' is restricted!");
}
return $page;
}
// Return deleted page
function getPageDelete($scheme, $address, $base, $location, $fileName, $rawData, $endOfLine)
{
$page = new YellowPage($this->yellow);
$page->setRequestInformation($scheme, $address, $base, $location, $fileName);
$page->parseData($this->normaliseLines($rawData, $endOfLine), false, 0);
$this->editContentFile($page, "delete");
if($this->plugin->getUserRestrictions($this->userEmail, $page->location, $page->fileName))
{
$page->error(500, "Page '".$page->get("title")."' is restricted!");
2016-04-12 13:58:56 +00:00
}
2014-07-25 10:46:58 +00:00
return $page;
}
// Return preview page
function getPagePreview($scheme, $address, $base, $location, $fileName, $rawData, $endOfLine)
{
$page = new YellowPage($this->yellow);
$page->setRequestInformation($scheme, $address, $base, $location, $fileName);
$page->parseData($this->normaliseLines($rawData, $endOfLine), false, 200);
$this->yellow->text->setLanguage($page->get("language"));
$page->set("pageClass", "page-preview");
$page->set("pageClass", $page->get("pageClass")." template-".$page->get("template"));
$output = "<div class=\"".$page->getHtml("pageClass")."\"><div class=\"content\">";
if($this->yellow->config->get("editToolbarButtons")!="none")
{
$output .= "<h1>".$page->getHtml("titleContent")."</h1>\n";
}
$output .= $page->getContent();
$output .= "</div></div>";
$page->setOutput($output);
return $page;
}
2018-04-29 15:48:46 +00:00
// Return uploaded file
function getFileUpload($scheme, $address, $base, $pageLocation, $fileNameTemp, $fileNameShort)
{
$file = new YellowPage($this->yellow);
$file->setRequestInformation($scheme, $address, $base, "/".$fileNameTemp, $fileNameTemp);
$file->parseData(null, false, 0);
$file->set("fileNameShort", $fileNameShort);
$this->editMediaFile($file, "upload");
$file->location = $this->getFileNewLocation($fileNameShort, $pageLocation, $file->get("fileNewLocation"));
$file->fileName = substru($file->location, 1);
while(is_file($file->fileName))
{
$fileNameShort = $this->getFileNext(basename($file->fileName));
$file->location = $this->getFileNewLocation($fileNameShort, $pageLocation, $file->get("fileNewLocation"));
$file->fileName = substru($file->location, 1);
if(++$fileCounter>999) break;
}
if(is_file($file->fileName)) $file->error(500, "File '".$file->get("fileNameShort")."' is not possible!");
return $file;
}
// Return page data including status information
2016-02-20 17:34:06 +00:00
function getPageData()
{
$data = array();
if($this->isUser())
{
$data["title"] = $this->yellow->toolbox->getMetaData($this->rawDataEdit, "title");
2016-02-20 17:34:06 +00:00
$data["rawDataSource"] = $this->rawDataSource;
$data["rawDataEdit"] = $this->rawDataEdit;
$data["rawDataNew"] = $this->getRawDataNew();
2016-08-16 08:16:13 +00:00
$data["rawDataOutput"] = strval($this->rawDataOutput);
$data["rawDataEndOfLine"] = $this->rawDataEndOfLine;
2017-02-17 13:52:55 +00:00
$data["scheme"] = $this->yellow->page->scheme;
$data["address"] = $this->yellow->page->address;
$data["base"] = $this->yellow->page->base;
$data["location"] = $this->yellow->page->location;
2016-02-20 17:34:06 +00:00
$data["parserSafeMode"] = $this->yellow->page->parserSafeMode;
}
2016-07-19 22:12:05 +00:00
if($this->action!="none") $data = array_merge($data, $this->getRequestData());
2016-05-15 16:35:10 +00:00
$data["action"] = $this->action;
$data["status"] = $this->status;
$data["statusCode"] = $this->yellow->page->statusCode;
2016-02-20 17:34:06 +00:00
return $data;
}
// Return configuration data including user information
function getConfigData()
2013-04-14 22:41:04 +00:00
{
2014-08-19 21:44:22 +00:00
$data = $this->yellow->config->getData("", "Location");
if($this->isUser())
{
2016-05-15 16:35:10 +00:00
$data["userEmail"] = $this->userEmail;
$data["userName"] = $this->plugin->users->getName($this->userEmail);
$data["userLanguage"] = $this->plugin->users->getLanguage($this->userEmail);
$data["userStatus"] = $this->plugin->users->getStatus($this->userEmail);
$data["userHome"] = $this->plugin->users->getHome($this->userEmail);
2016-08-13 15:48:18 +00:00
$data["userRestrictions"] = intval($this->isUserRestrictions());
$data["userWebmaster"] = intval($this->isUserWebmaster());
$data["serverScheme"] = $this->yellow->config->get("serverScheme");
$data["serverAddress"] = $this->yellow->config->get("serverAddress");
$data["serverBase"] = $this->yellow->config->get("serverBase");
2018-04-29 15:48:46 +00:00
$data["serverFileSizeMax"] = $this->yellow->toolbox->getNumberBytes(ini_get("upload_max_filesize"));
$data["serverVersion"] = "Datenstrom Yellow ".YellowCore::VERSION;
$data["serverPlugins"] = array();
foreach($this->yellow->plugins->plugins as $key=>$value)
{
$data["serverPlugins"][$key] = $value["plugin"];
}
2016-05-15 16:35:10 +00:00
$data["serverLanguages"] = array();
foreach($this->yellow->text->getLanguages() as $language)
{
$data["serverLanguages"][$language] = $this->yellow->text->getTextHtml("languageDescription", $language);
}
2018-04-29 15:48:46 +00:00
$data["editUploadExtensions"] = $this->yellow->config->get("editUploadExtensions");
$data["editKeyboardShortcuts"] = $this->yellow->config->get("editKeyboardShortcuts");
$data["editToolbarButtons"] = $this->getToolbarButtons("edit");
$data["emojiawesomeToolbarButtons"] = $this->getToolbarButtons("emojiawesome");
$data["fontawesomeToolbarButtons"] = $this->getToolbarButtons("fontawesome");
2014-08-19 21:44:22 +00:00
} else {
2018-05-02 07:45:30 +00:00
$data["editLoginEmail"] = $this->yellow->page->get("editLoginEmail");
$data["editLoginPassword"] = $this->yellow->page->get("editLoginPassword");
$data["editLoginRestrictions"] = intval($this->isLoginRestrictions());
2016-04-12 13:58:56 +00:00
}
2016-05-15 16:35:10 +00:00
if(defined("DEBUG") && DEBUG>=1) $data["debug"] = DEBUG;
2016-04-12 13:58:56 +00:00
return $data;
}
// Return request strings
function getRequestData()
{
$data = array();
foreach($_REQUEST as $key=>$value)
{
if($key=="password" || $key=="authtoken" || $key=="csrftoken" || $key=="actiontoken" || substru($key, 0, 7)=="rawdata") continue;
2016-04-12 13:58:56 +00:00
$data["request".ucfirst($key)] = trim($value);
2014-08-19 21:44:22 +00:00
}
return $data;
2013-04-14 22:41:04 +00:00
}
2014-05-15 11:53:54 +00:00
2016-08-13 15:48:18 +00:00
// Return text strings
function getTextData()
2016-04-12 13:58:56 +00:00
{
2017-02-17 13:52:55 +00:00
$textLanguage = $this->yellow->text->getData("language", $this->language);
$textEdit = $this->yellow->text->getData("edit", $this->language);
2017-02-17 13:52:55 +00:00
$textYellow = $this->yellow->text->getData("yellow", $this->language);
return array_merge($textLanguage, $textEdit, $textYellow);
2016-08-13 15:48:18 +00:00
}
// Return toolbar buttons
function getToolbarButtons($name)
{
if($name=="edit")
{
$toolbarButtons = $this->yellow->config->get("editToolbarButtons");
if($toolbarButtons=="auto")
{
$toolbarButtons = "";
if($this->yellow->plugins->isExisting("markdown")) $toolbarButtons = "preview, format, bold, italic, code, list, link, file";
if($this->yellow->plugins->isExisting("emojiawesome")) $toolbarButtons .= ", emojiawesome";
if($this->yellow->plugins->isExisting("fontawesome")) $toolbarButtons .= ", fontawesome";
if($this->yellow->plugins->isExisting("draft")) $toolbarButtons .= ", draft";
if($this->yellow->plugins->isExisting("markdown")) $toolbarButtons .= ", markdown";
}
} else {
$toolbarButtons = $this->yellow->config->get("{$name}ToolbarButtons");
}
return $toolbarButtons;
}
// Return end of line format
function getEndOfLine($rawData = "")
{
$endOfLine = $this->yellow->config->get("editEndOfLine");
if($endOfLine=="auto")
{
$rawData = empty($rawData) ? PHP_EOL : substru($rawData, 0, 4096);
$endOfLine = strposu($rawData, "\r")===false ? "lf" : "crlf";
}
return $endOfLine;
}
2016-08-13 15:48:18 +00:00
// Return raw data for new page
function getRawDataNew($location = "")
{
foreach($this->yellow->pages->path($this->yellow->page->location)->reverse() as $page)
{
if($page->isExisting("templateNew"))
{
$name = $this->yellow->lookup->normaliseName($page->get("templateNew"));
$fileName = strreplaceu("(.*)", $name, $this->yellow->config->get("configDir").$this->yellow->config->get("newFile"));
if(is_file($fileName)) break;
}
}
if(!is_file($fileName))
{
$name = $this->yellow->lookup->normaliseName($this->yellow->config->get("template"));
$fileName = strreplaceu("(.*)", $name, $this->yellow->config->get("configDir").$this->yellow->config->get("newFile"));
}
2016-08-13 15:48:18 +00:00
$rawData = $this->yellow->toolbox->readFile($fileName);
$rawData = preg_replace("/@timestamp/i", time(), $rawData);
2016-08-13 15:48:18 +00:00
$rawData = preg_replace("/@datetime/i", date("Y-m-d H:i:s"), $rawData);
$rawData = preg_replace("/@date/i", date("Y-m-d"), $rawData);
$rawData = preg_replace("/@usershort/i", strtok($this->plugin->users->getName($this->userEmail), " "), $rawData);
$rawData = preg_replace("/@username/i", $this->plugin->users->getName($this->userEmail), $rawData);
$rawData = preg_replace("/@userlanguage/i", $this->plugin->users->getLanguage($this->userEmail), $rawData);
2016-08-13 15:48:18 +00:00
if(!empty($location))
2016-04-12 13:58:56 +00:00
{
$rawData = $this->yellow->toolbox->setMetaData($rawData, "title", $this->yellow->toolbox->createTextTitle($location));
2016-04-12 13:58:56 +00:00
}
2016-08-13 15:48:18 +00:00
return $rawData;
2016-04-12 13:58:56 +00:00
}
// Return location for new/modified page
2018-04-29 15:48:46 +00:00
function getPageNewLocation($rawData, $pageLocation, $pageNewLocation)
2016-02-20 17:34:06 +00:00
{
$location = empty($pageNewLocation) ? "@title" : $pageNewLocation;
$location = preg_replace("/@title/i", $this->getPageNewTitle($rawData), $location);
2018-04-29 15:48:46 +00:00
$location = preg_replace("/@timestamp/i", $this->getPageNewData($rawData, "published", true, "U"), $location);
$location = preg_replace("/@date/i", $this->getPageNewData($rawData, "published", true, "Y-m-d"), $location);
$location = preg_replace("/@year/i", $this->getPageNewData($rawData, "published", true, "Y"), $location);
$location = preg_replace("/@month/i", $this->getPageNewData($rawData, "published", true, "m"), $location);
$location = preg_replace("/@day/i", $this->getPageNewData($rawData, "published", true, "d"), $location);
$location = preg_replace("/@tag/i", $this->getPageNewData($rawData, "tag", true), $location);
$location = preg_replace("/@author/i", $this->getPageNewData($rawData, "author", true), $location);
if(!preg_match("/^\//", $location))
2016-08-13 15:48:18 +00:00
{
$location = $this->yellow->lookup->getDirectoryLocation($pageLocation).$location;
2016-08-13 15:48:18 +00:00
}
return $location;
2016-08-13 15:48:18 +00:00
}
// Return title for new/modified page
function getPageNewTitle($rawData)
{
$title = $this->yellow->toolbox->getMetaData($rawData, "title");
$titleSlug = $this->yellow->toolbox->getMetaData($rawData, "titleSlug");
$value = empty($titleSlug) ? $title : $titleSlug;
$value = $this->yellow->lookup->normaliseName($value, true, false, true);
return trim(preg_replace("/-+/", "-", $value), "-");
}
2018-04-29 15:48:46 +00:00
// Return data for new/modified page
function getPageNewData($rawData, $key, $filterFirst = false, $dateFormat = "")
2016-08-13 15:48:18 +00:00
{
$value = $this->yellow->toolbox->getMetaData($rawData, $key);
if($filterFirst && preg_match("/^(.*?)\,(.*)$/", $value, $matches)) $value = $matches[1];
if(!empty($dateFormat)) $value = date($dateFormat, strtotime($value));
if(strempty($value)) $value = "none";
$value = $this->yellow->lookup->normaliseName($value, true, false, true);
return trim(preg_replace("/-+/", "-", $value), "-");
2016-08-13 15:48:18 +00:00
}
2018-04-29 15:48:46 +00:00
// Return location for new file
function getFileNewLocation($fileNameShort, $pageLocation, $fileNewLocation)
{
$location = empty($fileNewLocation) ? $this->yellow->config->get("editUploadNewLocation") : $fileNewLocation;
$location = preg_replace("/@timestamp/i", time(), $location);
$location = preg_replace("/@type/i", $this->yellow->toolbox->getFileType($fileNameShort), $location);
$location = preg_replace("/@group/i", $this->getFileNewGroup($fileNameShort), $location);
$location = preg_replace("/@folder/i", $this->getFileNewFolder($pageLocation), $location);
$location = preg_replace("/@filename/i", strtoloweru($fileNameShort), $location);
if(!preg_match("/^\//", $location))
{
$location = $this->yellow->config->get("mediaLocation").$location;
}
return $location;
}
// Return group for new file
function getFileNewGroup($fileNameShort)
{
$path = $this->yellow->config->get("mediaDir");
$fileType = $this->yellow->toolbox->getFileType($fileNameShort);
$fileName = $this->yellow->config->get(preg_match("/(gif|jpg|png|svg)$/", $fileType) ? "imageDir" : "downloadDir").$fileNameShort;
preg_match("#^$path(.+?)\/#", $fileName, $matches);
return strtoloweru($matches[1]);
}
// Return folder for new file
function getFileNewFolder($pageLocation)
{
$parentTopLocation = $this->yellow->pages->getParentTopLocation($pageLocation);
if($parentTopLocation==$this->yellow->pages->getHomeLocation($pageLocation)) $parentTopLocation .= "home";
return strtoloweru(trim($parentTopLocation, '/'));
}
2016-08-13 15:48:18 +00:00
2018-04-29 15:48:46 +00:00
// Return next title
function getTitleNext($rawData)
2016-08-13 15:48:18 +00:00
{
preg_match("/^(.*?)(\d*)$/", $this->yellow->toolbox->getMetaData($rawData, "title"), $matches);
$titleText = $matches[1];
$titleNumber = strempty($matches[2]) ? " 2" : $matches[2]+1;
return $titleText.$titleNumber;
2016-02-20 17:34:06 +00:00
}
2018-04-29 15:48:46 +00:00
// Return next file name
function getFileNext($fileNameShort)
{
preg_match("/^(.*?)(\d*)(\..*?)?$/", $fileNameShort, $matches);
$fileText = $matches[1];
$fileNumber = strempty($matches[2]) ? "-2" : $matches[2]+1;
$fileExtension = $matches[3];
return $fileText.$fileNumber.$fileExtension;
}
// Normalise text lines, convert line endings
function normaliseLines($text, $endOfLine = "lf")
{
if($endOfLine=="lf")
{
$text = preg_replace("/\R/u", "\n", $text);
} else {
$text = preg_replace("/\R/u", "\r\n", $text);
}
return $text;
}
2016-02-20 17:34:06 +00:00
// Create browser cookies
function createCookies($scheme, $address, $base, $email)
2017-01-05 09:39:42 +00:00
{
$expire = time() + $this->yellow->config->get("editLoginSessionTimeout");
$authToken = $this->plugin->users->createAuthToken($email, $expire);
$csrfToken = $this->plugin->users->createCsrfToken();
setcookie("authtoken", $authToken, $expire, "$base/", "", $scheme=="https", true);
setcookie("csrftoken", $csrfToken, $expire, "$base/", "", $scheme=="https", false);
2017-01-05 09:39:42 +00:00
}
// Destroy browser cookies
function destroyCookies($scheme, $address, $base)
2017-01-05 09:39:42 +00:00
{
setcookie("authtoken", "", 1, "$base/", "", $scheme=="https", true);
setcookie("csrftoken", "", 1, "$base/", "", $scheme=="https", false);
2017-01-05 09:39:42 +00:00
}
2016-04-12 13:58:56 +00:00
2016-08-13 15:48:18 +00:00
// Send mail to user
2017-02-17 13:52:55 +00:00
function sendMail($scheme, $address, $base, $email, $action)
2016-08-13 15:48:18 +00:00
{
if($action=="welcome" || $action=="information")
{
2017-02-17 13:52:55 +00:00
$url = "$scheme://$address$base/";
2016-08-13 15:48:18 +00:00
} else {
$expire = time() + 60*60*24;
$actionToken = $this->plugin->users->createActionToken($email, $action, $expire);
$url = "$scheme://$address$base"."/action:$action/email:$email/expire:$expire/actiontoken:$actionToken/";
2016-08-13 15:48:18 +00:00
}
if($action=="approve")
{
$account = $email;
$name = $this->yellow->config->get("author");
$email = $this->yellow->config->get("email");
} else {
$account = $email;
$name = $this->plugin->users->getName($email);
2016-08-13 15:48:18 +00:00
}
$language = $this->plugin->users->getLanguage($email);
2016-08-13 15:48:18 +00:00
if(!$this->yellow->text->isLanguage($language)) $language = $this->yellow->config->get("language");
$sitename = $this->yellow->config->get("sitename");
$prefix = "edit".ucfirst($action);
2016-08-13 15:48:18 +00:00
$message = $this->yellow->text->getText("{$prefix}Message", $language);
$message = preg_replace("/@useraccount/i", $account, $message);
$message = preg_replace("/@usershort/i", strtok($name, " "), $message);
$message = preg_replace("/@username/i", $name, $message);
$message = preg_replace("/@userlanguage/i", $language, $message);
2017-01-23 10:27:02 +00:00
$mailTo = mb_encode_mimeheader("$name")." <$email>";
2016-08-13 15:48:18 +00:00
$mailSubject = mb_encode_mimeheader($this->yellow->text->getText("{$prefix}Subject", $language));
2017-01-23 10:27:02 +00:00
$mailHeaders = mb_encode_mimeheader("From: $sitename")." <noreply>\r\n";
2017-02-17 13:52:55 +00:00
$mailHeaders .= mb_encode_mimeheader("X-Request-Url: $scheme://$address$base")."\r\n";
2016-08-13 15:48:18 +00:00
$mailHeaders .= mb_encode_mimeheader("X-Remote-Addr: $_SERVER[REMOTE_ADDR]")."\r\n";
$mailHeaders .= "Mime-Version: 1.0\r\n";
$mailHeaders .= "Content-Type: text/plain; charset=utf-8\r\n";
$mailMessage = "$message\r\n\r\n$url\r\n-- \r\n$sitename";
return mail($mailTo, $mailSubject, $mailMessage, $mailHeaders);
}
2018-04-29 15:48:46 +00:00
// Change content file
2017-11-04 16:11:34 +00:00
function editContentFile($page, $action)
{
if(!$page->isError())
{
foreach($this->yellow->plugins->plugins as $key=>$value)
{
if(method_exists($value["obj"], "onEditContentFile")) $value["obj"]->onEditContentFile($page, $action);
}
}
}
2018-04-29 15:48:46 +00:00
// Change media file
function editMediaFile($file, $action)
{
if(!$file->isError())
{
foreach($this->yellow->plugins->plugins as $key=>$value)
{
if(method_exists($value["obj"], "onEditMediaFile")) $value["obj"]->onEditMediaFile($file, $action);
}
}
}
2017-11-04 16:11:34 +00:00
// Check if active
2016-08-13 15:48:18 +00:00
function isActive()
{
return $this->active;
}
2016-05-15 16:35:10 +00:00
// Check if user is logged in
function isUser()
2016-04-12 13:58:56 +00:00
{
2016-05-15 16:35:10 +00:00
return !empty($this->userEmail);
2016-04-12 13:58:56 +00:00
}
2016-08-13 15:48:18 +00:00
// Check if user has restrictions
function isUserRestrictions()
{
return empty($this->userEmail) || $this->userRestrictions;
}
2014-05-15 11:53:54 +00:00
2016-08-13 15:48:18 +00:00
// Check if user is webmaster
function isUserWebmaster()
2014-05-15 11:53:54 +00:00
{
2016-08-13 15:48:18 +00:00
return !empty($this->userEmail) && $this->userEmail==$this->yellow->config->get("email");
2014-05-15 11:53:54 +00:00
}
// Check if login has restrictions
function isLoginRestrictions()
{
return $this->yellow->config->get("editLoginRestrictions");
}
2013-04-14 22:41:04 +00:00
}
2015-10-06 12:19:11 +00:00
class YellowUsers
2013-04-14 22:41:04 +00:00
{
2013-12-21 13:10:15 +00:00
var $yellow; //access to API
2013-04-14 22:41:04 +00:00
var $users; //registered users
2013-12-21 13:10:15 +00:00
function __construct($yellow)
2013-04-14 22:41:04 +00:00
{
2013-12-21 13:10:15 +00:00
$this->yellow = $yellow;
2013-04-14 22:41:04 +00:00
$this->users = array();
}
// Load users from file
2016-02-20 17:34:06 +00:00
function load($fileName)
2013-04-14 22:41:04 +00:00
{
2016-02-20 17:34:06 +00:00
if(defined("DEBUG") && DEBUG>=2) echo "YellowUsers::load file:$fileName<br/>\n";
$fileData = $this->yellow->toolbox->readFile($fileName);
foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
2013-04-14 22:41:04 +00:00
{
2016-02-20 17:34:06 +00:00
if(preg_match("/^\#/", $line)) continue;
2016-06-27 13:28:10 +00:00
preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
if(!empty($matches[1]) && !empty($matches[2]))
2013-04-14 22:41:04 +00:00
{
list($hash, $name, $language, $status, $stamp, $modified, $errors, $pending, $home) = explode(',', $matches[2]);
if($errors=="none") { $home=$pending; $pending=$errors; $errors=$modified; $modified=$stamp; $stamp=$matches[1]; } //TODO: remove later
$this->set($matches[1], $hash, $name, $language, $status, $stamp, $modified, $errors, $pending, $home);
2016-02-20 17:34:06 +00:00
if(defined("DEBUG") && DEBUG>=3) echo "YellowUsers::load email:$matches[1]<br/>\n";
2013-04-14 22:41:04 +00:00
}
}
}
2013-12-21 13:10:15 +00:00
2016-06-02 15:31:42 +00:00
// Clean users in file
function clean($fileName)
{
$fileData = $this->yellow->toolbox->readFile($fileName);
foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
{
2016-06-27 13:28:10 +00:00
preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
if(!empty($matches[1]) && !empty($matches[2]))
2016-06-02 15:31:42 +00:00
{
list($hash, $name, $language, $status, $stamp, $modified, $errors, $pending, $home) = explode(',', $matches[2]);
if($errors=="none") { $home=$pending; $pending=$errors; $errors=$modified; $modified=$stamp; $stamp=$this->createStamp(); } //TODO: remove later
if(strlenb($stamp)!=20) $stamp=$this->createStamp(); //TODO: remove later, converts old file format
2016-06-27 13:28:10 +00:00
if($status=="active" || $status=="inactive")
{
2017-01-03 13:11:44 +00:00
$pending = "none";
$fileDataNew .= "$matches[1]: $hash,$name,$language,$status,$stamp,$modified,$errors,$pending,$home\n";
2016-06-27 13:28:10 +00:00
}
} else {
2016-06-02 15:31:42 +00:00
$fileDataNew .= $line;
}
}
return $this->yellow->toolbox->createFile($fileName, $fileDataNew);
}
2016-04-12 13:58:56 +00:00
// Update users in file
function update($fileName, $email, $password = "", $name = "", $language = "", $status = "", $stamp = "", $modified = "", $errors = "", $pending = "", $home = "")
2016-04-12 13:58:56 +00:00
{
2016-08-13 15:48:18 +00:00
if(!empty($password)) $hash = $this->createHash($password);
2016-04-12 13:58:56 +00:00
if($this->isExisting($email))
{
$email = strreplaceu(',', '-', $email);
$hash = strreplaceu(',', '-', empty($hash) ? $this->users[$email]["hash"] : $hash);
$name = strreplaceu(',', '-', empty($name) ? $this->users[$email]["name"] : $name);
$language = strreplaceu(',', '-', empty($language) ? $this->users[$email]["language"] : $language);
$status = strreplaceu(',', '-', empty($status) ? $this->users[$email]["status"] : $status);
$stamp = strreplaceu(',', '-', empty($stamp) ? $this->users[$email]["stamp"] : $stamp);
2016-08-16 08:16:13 +00:00
$modified = strreplaceu(',', '-', empty($modified) ? time() : $modified);
2017-07-05 10:25:25 +00:00
$errors = strreplaceu(',', '-', empty($errors) ? "0" : $errors);
2016-06-27 13:28:10 +00:00
$pending = strreplaceu(',', '-', empty($pending) ? $this->users[$email]["pending"] : $pending);
2016-04-12 13:58:56 +00:00
$home = strreplaceu(',', '-', empty($home) ? $this->users[$email]["home"] : $home);
} else {
$email = strreplaceu(',', '-', empty($email) ? "none" : $email);
$hash = strreplaceu(',', '-', empty($hash) ? "none" : $hash);
$name = strreplaceu(',', '-', empty($name) ? $this->yellow->config->get("sitename") : $name);
$language = strreplaceu(',', '-', empty($language) ? $this->yellow->config->get("language") : $language);
$status = strreplaceu(',', '-', empty($status) ? $this->yellow->config->get("editUserStatus") : $status);
$stamp = strreplaceu(',', '-', empty($stamp) ? $this->createStamp() : $stamp);
2016-08-16 08:16:13 +00:00
$modified = strreplaceu(',', '-', empty($modified) ? time() : $modified);
2017-07-05 10:25:25 +00:00
$errors = strreplaceu(',', '-', empty($errors) ? "0" : $errors);
2017-01-03 13:11:44 +00:00
$pending = strreplaceu(',', '-', empty($pending) ? "none" : $pending);
$home = strreplaceu(',', '-', empty($home) ? $this->yellow->config->get("editUserHome") : $home);
2016-04-12 13:58:56 +00:00
}
$this->set($email, $hash, $name, $language, $status, $stamp, $modified, $errors, $pending, $home);
2016-04-12 13:58:56 +00:00
$fileData = $this->yellow->toolbox->readFile($fileName);
foreach($this->yellow->toolbox->getTextLines($fileData) as $line)
{
2016-06-27 13:28:10 +00:00
preg_match("/^\s*(.*?)\s*:\s*(.*?)\s*$/", $line, $matches);
2016-04-12 13:58:56 +00:00
if(!empty($matches[1]) && $matches[1]==$email)
{
$fileDataNew .= "$email: $hash,$name,$language,$status,$stamp,$modified,$errors,$pending,$home\n";
2016-04-12 13:58:56 +00:00
$found = true;
} else {
$fileDataNew .= $line;
}
}
if(!$found) $fileDataNew .= "$email: $hash,$name,$language,$status,$stamp,$modified,$errors,$pending,$home\n";
2016-04-12 13:58:56 +00:00
return $this->yellow->toolbox->createFile($fileName, $fileDataNew);
}
// Set user data
function set($email, $hash, $name, $language, $status, $stamp, $modified, $errors, $pending, $home)
{
$this->users[$email] = array();
$this->users[$email]["email"] = $email;
$this->users[$email]["hash"] = $hash;
$this->users[$email]["name"] = $name;
$this->users[$email]["language"] = $language;
2015-10-06 12:19:11 +00:00
$this->users[$email]["status"] = $status;
$this->users[$email]["stamp"] = $stamp;
2016-08-16 08:16:13 +00:00
$this->users[$email]["modified"] = $modified;
2017-07-05 10:25:25 +00:00
$this->users[$email]["errors"] = $errors;
2016-06-27 13:28:10 +00:00
$this->users[$email]["pending"] = $pending;
$this->users[$email]["home"] = $home;
}
// Check user authentication from email and password
function checkAuthLogin($email, $password)
2013-04-14 22:41:04 +00:00
{
$algorithm = $this->yellow->config->get("editUserHashAlgorithm");
2015-10-06 12:19:11 +00:00
return $this->isExisting($email) && $this->users[$email]["status"]=="active" &&
$this->yellow->toolbox->verifyHash($password, $algorithm, $this->users[$email]["hash"]);
2013-04-14 22:41:04 +00:00
}
// Check user authentication from tokens
function checkAuthToken($authToken, $csrfTokenExpected, $csrfTokenReceived, $ignoreCsrfToken)
2016-04-12 13:58:56 +00:00
{
$signature = "$5y$".substrb($authToken, 0, 96);
$email = $this->getAuthEmail($authToken);
$expire = $this->getAuthExpire($authToken);
return $expire>time() && $this->isExisting($email) && $this->users[$email]["status"]=="active" &&
$this->yellow->toolbox->verifyHash($this->users[$email]["hash"]."auth".$expire, "sha256", $signature) &&
($this->verifyToken($csrfTokenExpected, $csrfTokenReceived) || $ignoreCsrfToken);
2016-04-12 13:58:56 +00:00
}
// Check action token
function checkActionToken($actionToken, $email, $action, $expire)
{
$signature = "$5y$".$actionToken;
return $expire>time() && $this->isExisting($email) &&
$this->yellow->toolbox->verifyHash($this->users[$email]["hash"].$action.$expire, "sha256", $signature);
}
// Create authentication token
function createAuthToken($email, $expire)
{
$signature = $this->yellow->toolbox->createHash($this->users[$email]["hash"]."auth".$expire, "sha256");
if(empty($signature)) $signature = "padd"."error-hash-algorithm-sha256";
return substrb($signature, 4).$this->getStamp($email).dechex($expire);
}
// Create action token
function createActionToken($email, $action, $expire)
{
$signature = $this->yellow->toolbox->createHash($this->users[$email]["hash"].$action.$expire, "sha256");
if(empty($signature)) $signature = "padd"."error-hash-algorithm-sha256";
return substrb($signature, 4);
}
// Create CSRF token
function createCsrfToken()
{
return $this->yellow->toolbox->createSalt(64);
}
2016-08-13 15:48:18 +00:00
// Create password hash
function createHash($password)
2013-04-14 22:41:04 +00:00
{
$algorithm = $this->yellow->config->get("editUserHashAlgorithm");
$cost = $this->yellow->config->get("editUserHashCost");
2016-08-13 15:48:18 +00:00
$hash = $this->yellow->toolbox->createHash($password, $algorithm, $cost);
if(empty($hash)) $hash = "error-hash-algorithm-$algorithm";
return $hash;
2013-04-14 22:41:04 +00:00
}
// Create user stamp
function createStamp()
2013-04-14 22:41:04 +00:00
{
$stamp = $this->yellow->toolbox->createSalt(20);
while($this->getAuthEmail("none", $stamp)) $stamp = $this->yellow->toolbox->createSalt(20);
return $stamp;
2013-04-14 22:41:04 +00:00
}
// Return user email from authentication, timing attack safe email lookup
function getAuthEmail($authToken, $stamp = "")
{
if(empty($stamp)) $stamp = substrb($authToken, 96, 20);
foreach($this->users as $key=>$value)
{
if($this->verifyToken($value["stamp"], $stamp)) $email = $key;
}
return $email;
}
2016-08-13 15:48:18 +00:00
// Return expiration time from authentication
function getAuthExpire($authToken)
{
return hexdec(substrb($authToken, 96+20));
}
2016-04-12 13:58:56 +00:00
// Return user hash
2017-07-05 10:25:25 +00:00
function getHash($email)
2016-04-12 13:58:56 +00:00
{
return $this->isExisting($email) ? $this->users[$email]["hash"] : "";
}
2013-04-14 22:41:04 +00:00
// Return user name
2017-07-05 10:25:25 +00:00
function getName($email)
2013-04-14 22:41:04 +00:00
{
return $this->isExisting($email) ? $this->users[$email]["name"] : "";
}
// Return user language
2017-07-05 10:25:25 +00:00
function getLanguage($email)
2013-04-14 22:41:04 +00:00
{
return $this->isExisting($email) ? $this->users[$email]["language"] : "";
}
2015-10-06 12:19:11 +00:00
// Return user status
2017-07-05 10:25:25 +00:00
function getStatus($email)
2015-10-06 12:19:11 +00:00
{
return $this->isExisting($email) ? $this->users[$email]["status"] : "";
}
// Return user stamp
function getStamp($email)
{
return $this->isExisting($email) ? $this->users[$email]["stamp"] : "";
}
2016-08-16 08:16:13 +00:00
// Return user modified
2017-07-05 10:25:25 +00:00
function getModified($email)
2016-08-16 08:16:13 +00:00
{
return $this->isExisting($email) ? $this->users[$email]["modified"] : "";
}
2017-07-05 10:25:25 +00:00
// Return user errors
function getErrors($email)
{
return $this->isExisting($email) ? $this->users[$email]["errors"] : "";
}
2016-06-27 13:28:10 +00:00
// Return user pending
2017-07-05 10:25:25 +00:00
function getPending($email)
2016-06-27 13:28:10 +00:00
{
return $this->isExisting($email) ? $this->users[$email]["pending"] : "";
}
// Return user home
2017-07-05 10:25:25 +00:00
function getHome($email)
{
return $this->isExisting($email) ? $this->users[$email]["home"] : "";
}
2013-04-14 22:41:04 +00:00
2015-05-05 16:11:43 +00:00
// Return number of users
function getNumber()
{
return count($this->users);
}
2016-05-15 16:35:10 +00:00
2016-08-13 15:48:18 +00:00
// Return user data
function getData()
2016-05-15 16:35:10 +00:00
{
2016-08-13 15:48:18 +00:00
$data = array();
foreach($this->users as $key=>$value)
{
2017-02-17 13:52:55 +00:00
$name = $value["name"]; if(preg_match("/\s/", $name)) $name = "\"$name\"";
$language = $value["language"]; if(preg_match("/\s/", $language)) $language = "\"$language\"";
$status = $value["status"]; if(preg_match("/\s/", $status)) $status = "\"$status\"";
$data[$key] = "$value[email] - $name $language $status";
2016-08-13 15:48:18 +00:00
if($value["home"]!="/") $data[$key] .= " restrictions";
}
2017-11-30 23:31:43 +00:00
uksort($data, "strnatcasecmp");
2016-08-13 15:48:18 +00:00
return $data;
2016-05-15 16:35:10 +00:00
}
2016-08-16 08:16:13 +00:00
// Verify that token is not empty and identical, timing attack safe text string comparison
function verifyToken($tokenExpected, $tokenReceived) //TODO: remove later, use directly from core after next release
{
$ok = false;
$lengthExpected = strlenb($tokenExpected);
$lengthReceived = strlenb($tokenReceived);
if($lengthExpected!=0 && $lengthReceived!=0)
{
$ok = $lengthExpected==$lengthReceived;
for($i=0; $i<$lengthReceived; ++$i) $ok &= $tokenExpected[$i<$lengthExpected ? $i : 0]==$tokenReceived[$i];
}
return $ok;
}
2016-08-16 08:16:13 +00:00
// Check if user is taken
function isTaken($email)
{
$taken = false;
if($this->isExisting($email))
{
$status = $this->users[$email]["status"];
$reserved = $this->users[$email]["modified"] + 60*60*24;
if($status=="active" || $status=="inactive" || $reserved>time()) $taken = true;
}
return $taken;
}
2013-04-14 22:41:04 +00:00
// Check if user exists
function isExisting($email)
{
return !is_null($this->users[$email]);
}
}
2015-10-06 12:19:11 +00:00
class YellowMerge
{
var $yellow; //access to API
2016-07-19 22:12:05 +00:00
const ADD = '+'; //merge types
const MODIFY = '*';
const REMOVE = '-';
const SAME = ' ';
function __construct($yellow)
{
$this->yellow = $yellow;
}
2016-07-19 22:12:05 +00:00
// Merge text, null if not possible
function merge($textSource, $textMine, $textYours, $showDiff = false)
{
2016-07-19 22:12:05 +00:00
if($textMine!=$textYours)
{
$diffMine = $this->buildDiff($textSource, $textMine);
$diffYours = $this->buildDiff($textSource, $textYours);
$diff = $this->mergeDiff($diffMine, $diffYours);
$output = $this->getOutput($diff, $showDiff);
} else {
$output = $textMine;
}
return $output;
}
// Build differences to common source
function buildDiff($textSource, $textOther)
{
$diff = array();
$lastRemove = -1;
$textStart = 0;
$textSource = $this->yellow->toolbox->getTextLines($textSource);
$textOther = $this->yellow->toolbox->getTextLines($textOther);
$sourceEnd = $sourceSize = count($textSource);
$otherEnd = $otherSize = count($textOther);
while($textStart<$sourceEnd && $textStart<$otherEnd && $textSource[$textStart]==$textOther[$textStart]) ++$textStart;
while($textStart<$sourceEnd && $textStart<$otherEnd && $textSource[$sourceEnd-1]==$textOther[$otherEnd-1])
{
--$sourceEnd; --$otherEnd;
}
2016-07-19 22:12:05 +00:00
for($pos=0; $pos<$textStart; ++$pos) array_push($diff, array(YellowMerge::SAME, $textSource[$pos], false));
$lcs = $this->buildDiffLCS($textSource, $textOther, $textStart, $sourceEnd-$textStart, $otherEnd-$textStart);
for($x=0,$y=0,$xEnd=$otherEnd-$textStart,$yEnd=$sourceEnd-$textStart; $x<$xEnd || $y<$yEnd;)
{
$max = $lcs[$y][$x];
if($y<$yEnd && $lcs[$y+1][$x]==$max)
{
2016-07-19 22:12:05 +00:00
array_push($diff, array(YellowMerge::REMOVE, $textSource[$textStart+$y], false));
if($lastRemove==-1) $lastRemove = count($diff)-1;
++$y;
continue;
}
if($x<$xEnd && $lcs[$y][$x+1]==$max)
{
2016-07-19 22:12:05 +00:00
if($lastRemove==-1 || $diff[$lastRemove][0]!=YellowMerge::REMOVE)
{
2016-07-19 22:12:05 +00:00
array_push($diff, array(YellowMerge::ADD, $textOther[$textStart+$x], false));
$lastRemove = -1;
} else {
2016-07-19 22:12:05 +00:00
$diff[$lastRemove] = array(YellowMerge::MODIFY, $textOther[$textStart+$x], false);
++$lastRemove; if(count($diff)==$lastRemove) $lastRemove = -1;
}
++$x;
continue;
}
2016-07-19 22:12:05 +00:00
array_push($diff, array(YellowMerge::SAME, $textSource[$textStart+$y], false));
$lastRemove = -1;
++$x;
++$y;
}
2016-07-19 22:12:05 +00:00
for($pos=$sourceEnd;$pos<$sourceSize; ++$pos) array_push($diff, array(YellowMerge::SAME, $textSource[$pos], false));
return $diff;
}
// Build longest common subsequence
function buildDiffLCS($textSource, $textOther, $textStart, $yEnd, $xEnd)
{
$lcs = array_fill(0, $yEnd+1, array_fill(0, $xEnd+1, 0));
for($y=$yEnd-1; $y>=0; --$y)
{
for($x=$xEnd-1; $x>=0; --$x)
{
2016-07-19 22:12:05 +00:00
if($textSource[$textStart+$y]==$textOther[$textStart+$x])
{
$lcs[$y][$x] = $lcs[$y+1][$x+1]+1;
} else {
$lcs[$y][$x] = max($lcs[$y][$x+1], $lcs[$y+1][$x]);
}
}
}
return $lcs;
}
// Merge differences
function mergeDiff($diffMine, $diffYours)
{
$diff = array();
$posMine = $posYours = 0;
while($posMine<count($diffMine) && $posYours<count($diffYours))
{
$typeMine = $diffMine[$posMine][0];
$typeYours = $diffYours[$posYours][0];
2016-07-19 22:12:05 +00:00
if($typeMine==YellowMerge::SAME)
{
array_push($diff, $diffYours[$posYours]);
2016-07-19 22:12:05 +00:00
} else if($typeYours==YellowMerge::SAME) {
array_push($diff, $diffMine[$posMine]);
2016-07-19 22:12:05 +00:00
} else if($typeMine==YellowMerge::ADD && $typeYours==YellowMerge::ADD) {
$this->mergeConflict($diff, $diffMine[$posMine], $diffYours[$posYours], false);
2016-07-19 22:12:05 +00:00
} else if($typeMine==YellowMerge::MODIFY && $typeYours==YellowMerge::MODIFY) {
$this->mergeConflict($diff, $diffMine[$posMine], $diffYours[$posYours], false);
2016-07-19 22:12:05 +00:00
} else if($typeMine==YellowMerge::REMOVE && $typeYours==YellowMerge::REMOVE) {
array_push($diff, $diffMine[$posMine]);
2016-07-19 22:12:05 +00:00
} else if($typeMine==YellowMerge::ADD) {
array_push($diff, $diffMine[$posMine]);
2016-07-19 22:12:05 +00:00
} else if($typeYours==YellowMerge::ADD) {
array_push($diff, $diffYours[$posYours]);
} else {
$this->mergeConflict($diff, $diffMine[$posMine], $diffYours[$posYours], true);
}
2015-10-06 12:19:11 +00:00
if(defined("DEBUG") && DEBUG>=2) echo "YellowMerge::mergeDiff $typeMine $typeYours pos:$posMine\t$posYours<br/>\n";
2016-07-19 22:12:05 +00:00
if($typeMine==YellowMerge::ADD || $typeYours==YellowMerge::ADD)
{
2016-07-19 22:12:05 +00:00
if($typeMine==YellowMerge::ADD) ++$posMine;
if($typeYours==YellowMerge::ADD) ++$posYours;
} else {
++$posMine;
++$posYours;
}
}
for(;$posMine<count($diffMine); ++$posMine)
{
array_push($diff, $diffMine[$posMine]);
$typeMine = $diffMine[$posMine][0]; $typeYours = ' ';
2015-10-06 12:19:11 +00:00
if(defined("DEBUG") && DEBUG>=2) echo "YellowMerge::mergeDiff $typeMine $typeYours pos:$posMine\t$posYours<br/>\n";
}
for(;$posYours<count($diffYours); ++$posYours)
{
array_push($diff, $diffYours[$posYours]);
$typeYours = $diffYours[$posYours][0]; $typeMine = ' ';
2015-10-06 12:19:11 +00:00
if(defined("DEBUG") && DEBUG>=2) echo "YellowMerge::mergeDiff $typeMine $typeYours pos:$posMine\t$posYours<br/>\n";
}
return $diff;
}
// Merge potential conflict
function mergeConflict(&$diff, $diffMine, $diffYours, $conflict)
{
if(!$conflict && $diffMine[1]==$diffYours[1])
{
array_push($diff, $diffMine);
} else {
array_push($diff, array($diffMine[0], $diffMine[1], true));
array_push($diff, array($diffYours[0], $diffYours[1], true));
}
}
2016-07-19 22:12:05 +00:00
// Return merged text, null if not possible
function getOutput($diff, $showDiff = false)
{
$output = "";
if(!$showDiff)
{
for($i=0; $i<count($diff); ++$i)
{
2016-07-19 22:12:05 +00:00
if($diff[$i][0]!=YellowMerge::REMOVE) $output .= $diff[$i][1];
$conflict |= $diff[$i][2];
}
} else {
for($i=0; $i<count($diff); ++$i)
{
$output .= $diff[$i][2] ? "! " : $diff[$i][0].' ';
$output .= $diff[$i][1];
}
}
2016-07-19 22:12:05 +00:00
return !$conflict ? $output : null;
}
}
2013-04-14 22:41:04 +00:00
$yellow->plugins->register("edit", "YellowEdit", YellowEdit::VERSION);
2017-06-07 19:33:55 +00:00
?>