Commenting

This commit is contained in:
Collin 2024-09-24 09:32:01 +02:00
parent a4d8cb524d
commit 44a1079d9d
6 changed files with 165 additions and 80 deletions

View File

@ -2,52 +2,65 @@
namespace LonaDB\Functions;
//Encryption/decryption
define('AES_256_CBC', 'aes-256-cbc');
//Load autoload from composer
require 'vendor/autoload.php';
//Load Main file and LonaFunction class
use LonaDB\LonaDB;
use LonaDB\Functions\LonaFunction;
class FunctionManager{
//Create all variables
private LonaDB $LonaDB;
private array $Functions;
public function __construct(LonaDB $lonaDB){
$this->LonaDB = $lonaDB;
//Initialize functions array
$this->Functions = array();
//Check if directory "data/functions/" exists, create if it doesn't
if(!is_dir("data/")) mkdir("data/");
if(!is_dir("data/functions/")) mkdir("data/functions/");
//Loop through all files and folders in "data/functions/"
foreach (new \DirectoryIterator('data/functions') as $fileInfo) {
//Check if file extension is ".lona"
if(str_ends_with($fileInfo->getFilename(), ".lona")){
//Initialize function instance
$this->Functions[substr($fileInfo->getFilename(), 0, -5)] = new LonaFunction($this->LonaDB, $fileInfo->getFilename());
}
}
}
public function GetFunction(string $name) : mixed {
//Check if a function with that name exists
if(!$this->Functions[$name]) return false;
//Return function instance
return $this->Functions[$name];
}
public function Create(string $name, string $content) : bool {
//Check if a function with that name exists
if($this->Functions[$name]) return false;
//Generate IV
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(AES_256_CBC));
//Encrypt function script
$encrypted = openssl_encrypt(json_encode($content), AES_256_CBC, $this->LonaDB->config["encryptionKey"], 0, $iv);
//Save
file_put_contents("./data/functions/".$name.".lona", $encrypted.":".base64_encode($iv));
//Initialize function instance
$this->Functions[$name] = new LonaFunction($this->LonaDB, $name . ".lona");
return true;
}
public function Delete(string $name) : bool {
//Check if function exists
if(!$this->Functions[$name]) return false;
//Delete function file and instance
unset($this->Functions[$name]);
unlink("./data/functions/".$name.".lona");
return true;

View File

@ -2,39 +2,51 @@
namespace LonaDB\Functions;
//Encryption/decryption
define('AES_256_CBC', 'aes-256-cbc');
//Load Main file
use LonaDB\LonaDB;
class LonaFunction{
//Create all variables
private string $file;
public string $Name;
private array $data;
private array $functions;
private LonaDB $LonaDB;
public function __construct(LonaDB $lonaDB, string $name){
$this->LonaDB = $lonaDB;
$this->LonaDB->Logger->Load("Trying to load function '".$name."'");
$this->LonaDB->Logger->Load("Loading function '".$name."'");
//Split encrypted function from IV
$parts = explode(':', file_get_contents("./data/functions/".$name));
//Decrypt function
$temp = json_decode(openssl_decrypt($parts[0], AES_256_CBC, $this->LonaDB->config["encryptionKey"], 0, base64_decode($parts[1])), true);
//Get function name
$this->file = substr($name, 0, -5);
$this->Name = $this->file;
$function = "\$this->data['" . $this->Name . "'] = new class {\n";
//Create a eval script to add the function to the functions array
//
//We are using an array because overwriting/defining a function inside eval didn't work for us
//Our workaround is creating a class instance with a run function which is our Lona function
$function = "\$this->functions['" . $this->Name . "'] = new class {\n";
$function .= "public function run(\$LonaDB, \$data, \$server, \$fd) {\n";
$function .= $temp;
$function .= "\n} \n};";
//Add the function to the array
eval($function);
$this->LonaDB->Logger->Load("Function '" . $this->Name . "' has been loaded");
}
public function Execute(LonaDB $LonaDB, array $data, $server, $fd) : mixed {
return $this->data[$this->Name]->run($LonaDB, $data, $server, $fd);
//Run function
return $this->functions[$this->Name]->run($LonaDB, $data, $server, $fd);
}
}

View File

@ -2,12 +2,15 @@
namespace LonaDB\Plugins;
//Load autoload from composer
require 'vendor/autoload.php';
//Load Main file and Logger class
use LonaDB\LonaDB;
use LonaDB\Logger;
require 'vendor/autoload.php';
class PluginBase{
//Create all variables
private LonaDB $LonaDB;
private string $Name;
private string $Version;
@ -20,19 +23,20 @@ class PluginBase{
$this->GetLogger()->Load("Loading Plugin '" . $this->Name . "'");
}
public function onEnable() : void {
$this->GetLogger()->Info("Plugin '" . $this->Name . "' has been loaded");
}
//Get LonaDB instance
final public function GetLonaDB() : LonaDB { return $this->LonaDB; }
//Get Logger instance
final public function GetLogger() : Logger { return $this->LonaDB->Logger; }
//Get own plugin name
final public function GetName() : string { return $this->Name; }
//Get own plugin version
final public function GetVersion() : string { return $this->Version; }
//Events
public function onEnable() : void { $this->GetLogger()->Info("Plugin '" . $this->Name . "' has been loaded"); }
public function onTableCreate(string $executor, string $name) : void {}
public function onTableDelete(string $executor, string $name) : void {}
public function onValueSet(string $executor, string $name, string $value) : void {}

View File

@ -2,10 +2,14 @@
namespace LonaDB\Plugins;
//Load autoload from composer
require 'vendor/autoload.php';
//Load Main file
use LonaDB\LonaDB;
class PluginManager{
//Create all variables
private LonaDB $LonaDB;
private array $Plugins;
private array $EnabledPlugins;
@ -14,42 +18,60 @@ class PluginManager{
public function __construct(LonaDB $lonaDB) {
$this->LonaDB = $lonaDB;
//Initialize plugins array
$this->Plugins = array();
}
public function LoadPlugins () : void {
//Check if plugins have already been loaded
if($this->Loaded = true) return;
$this->Loaded = true;
//Check if "plugins/" directory exists, create if it doesn't
if(!is_dir("plugins/")) mkdir("plugins/");
//For all files and folders in "plugins/"
$results = scandir("plugins/");
foreach($results as $r){
//Check if file ends with ".phar" => Plugin has been compiled
if(str_ends_with($r, ".phar")){
//Load PHAR file
$phar = new \Phar("plugins/" . $r, 0);
//Loop through all files in the PHAR archive
foreach (new \RecursiveIteratorIterator($phar) as $file) {
//Check for plugin.json
if($file->getFileName() === "plugin.json") {
//Get configuration from plugin.json
$conf = json_decode(file_get_contents($file->getPathName()), true);
//Generate path variable for the file
eval("\$path = substr(\$file->getPathName(), 0, -". strlen($file->getFileName()) .");");
}
}
//Check the configuration
if($conf['main'] && $conf['main']['path'] && $conf['main']['class'] && $conf['main']['namespace'] && $conf['name']){
//Check if main file declared in plugin.json exists
file_put_contents($path . $conf['main']['path'], file_get_contents($path . $conf['main']['path']));
if(file_get_contents($path. $conf['main']['path']) !== ""){
try{
//Load PHAR
$this->load_classphp($path, $phar);
//Add it to the Plugins array
eval("\$this->Plugins[\$conf['name']] = new " . $conf['main']['namespace'] . "\\" . $conf['main']['class'] . "(\$this->LonaDB, \$conf['name'], \$conf['version']);");
//Create a thread for it
$pid = @ pcntl_fork();
if( $pid == -1 ) {
throw new Exception( $this->getError( Thread::COULD_NOT_FORK ), Thread::COULD_NOT_FORK );
}
if( $pid ) {
//Save thread process ID
$this->pids[$conf['name']] = $pid;
}
else {
//Run plugin's onEnable event
$this->Plugins[$conf['name']]->onEnable();
}
}
@ -63,39 +85,47 @@ class PluginManager{
$this->LonaDB->Logger->Error("Could not load the plugin in '" . $r . "'");
}
}
//Load plugin from folder => Plugin hasn't been compiled
else if($r != "." && $r !== ".."){
//Scan "plugins/$foler"
$debugscan = scandir("plugins/" . $r);
//Check if plugin.json is inside the folder
if(in_array("plugin.json", $debugscan)) $conf = json_decode(file_get_contents("plugins/" . $r . "/plugin.json"), true);
//Check configuration
if($conf['main'] && $conf['main']['path'] && $conf['main']['class'] && $conf['main']['namespace'] && $conf['name']){
//Check if main file exists
file_put_contents("plugins/" . $r . "/" . $conf['main']['path'], file_get_contents("plugins/" . $r . "/" . $conf['main']['path']));
if(file_get_contents("plugins/" . $r . "/" . $conf['main']['path']) !== ""){
try{
//Load all PHP files in the folder
$this->load_classphp("plugins/" . $r . "/");
//Check if the plugin should be built
if($conf['build']){
//Build the PHAR
$phar = new \Phar("plugins/".$conf['name']."-".$conf['version'].".phar", 0, "plugins/".$conf['name']."-".$conf['version'].".phar");
$phar->buildFromDirectory("plugins/".$r."/");
$phar->buildFromDirectory("plugins/".$r."/");
$phar->setDefaultStub($conf['main']['namespace'].'/'.$conf['main']['class'].'.php', $conf['main']['namespace'].'/'.$conf['main']['class'].'.php');
$phar->setAlias($conf['name']."-".$conf['version'].".phar");
$phar->stopBuffering();
}
//Add plugin to the plugins array
eval("\$this->Plugins[\$conf['name']] = new " . $conf['main']['namespace'] . "\\" . $conf['main']['class'] . "(\$this->LonaDB, \$conf['name'], \$conf['version']);");
//Create a thread for the plugin
$pid = @ pcntl_fork();
if( $pid == -1 ) {
throw new Exception( $this->getError( Thread::COULD_NOT_FORK ), Thread::COULD_NOT_FORK );
}
if( $pid ) {
//Save the process ID
$this->pids[$conf['name']] = $pid;
}
else {
//Run the onEnable event
$this->Plugins[$conf['name']]->onEnable();
}
}
@ -113,40 +143,53 @@ class PluginManager{
}
public function KillThreads() : void {
//Loop through all process IDs
foreach($pid as $this->pids) {
//Kill the thread
posix_kill( $pid, SIGKILL );
}
$this->LonaDB->Logger->Info("Plugin threads have been killed");
}
public function GetPlugin(string $name) : mixed {
//Return plugin instance of ot exists
if($this->Plugins[$name]) return $this->Plugins[$name];
else return false;
}
private function load_classphp(string $path, \Phar $phar = null) : void {
//Check if loading from PHAR
if(str_starts_with($path, "phar")){
//Loop through PHAR
foreach (new \RecursiveIteratorIterator($phar) as $file) {
//Load file if its a PHP file
if(str_ends_with($file->getPathName(), ".php")) require_once $file->getPathName();
}
}
//Remove the last "/" if its the last character in the path name
if(str_ends_with($path, "/")) $path = substr($path, 0, -1);
//Scan directory
$items = glob( $path . "/*" );
//Loop through the directory
foreach( $items as $item ) {
//Check if file ends with PHP
$isPhp = str_ends_with($item, ".php");
if ( $isPhp ) {
//Load file
require_once $item;
} else{
//If its a folder, load PHP files inside
$this->load_classphp( $item . "/" );
}
}
}
public function RunEvent(string $executor, string $event, Array $arguments) : void {
//Loop through all plugins
foreach($this->Plugins as $pluginName => $pluginInstance) {
//Run event identified by name
switch($event){
case "tableCreate":
$pluginInstance->onTableCreate($executor, $arguments['name']);

View File

@ -21,131 +21,127 @@ class Table{
public function __construct(LonaDB $lonaDB, bool $create, string $name, string $owner = ""){
$this->LonaDB = $lonaDB;
//Check if this instance is used to create the table
if(!$create){
$this->LonaDB->Logger->Load("Trying to load table '".$name."'");
//Split encrypted file content and IV
$parts = explode(':', file_get_contents("./data/tables/".$name));
//Decrypt table data and load it as a JSON object
$temp = json_decode(openssl_decrypt($parts[0], AES_256_CBC, $this->LonaDB->config["encryptionKey"], 0, base64_decode($parts[1])), true);
//Load table informations
$this->file = substr($name, 0, -5);
$this->data = $temp["data"];
$this->permissions = $temp["permissions"];
$this->Owner = $temp["owner"];
}
else{
//Instance is used to create the table
else {
$this->LonaDB->Logger->Table("Trying to generate table '".$name."'");
//Load table informations and create empty data and permissions array
$this->file = $name;
$this->data = array();
$this->permissions = array();
$this->Owner = $owner;
//Save the empty table
$this->Save();
}
$this->Name = $this->file;
}
public function GetData() : array {
return $this->data;
}
//Return an array of all variables in the table
public function GetData() : array { return $this->data; }
public function GetOwner(string $user = "") : string {
if($user === "") return $this->Owner;
$this->LonaDB->Logger->Table("(".$this->file.") User '".$user."' is trying to get the owner name.");
return $this->Owner;
}
//Return the table owner's name
public function GetOwner(string $user = "") : string { return $this->Owner; }
public function SetOwner(string $name, string $user) : bool {
$this->LonaDB->Logger->Table("(".$this->file.") User '".$user."' is trying to change the owner to '".$name."'");
//Check if the executing user is either root or the owner of the table
if($user !== "root" && $user !== $this->Owner) return false;
//Change the owner and save
$this->Owner = $name;
$this->Save();
return true;
}
public function Set(string $name, mixed $value, string $user) : bool {
$this->LonaDB->Logger->Table("(".$this->file.") User '".$user."' is trying to set the variable '".$name."' to '".strval($value)."'");
//Check if the executing user has write permissions on this table
if(!$this->CheckPermission($user, "write")) return false;
//Set the variable and save
$this->data[$name] = $value;
$this->Save();
$this->LonaDB->Logger->Table("(".$this->file.") User '".$user."' set the variable '".$name."' to '".strval($value)."'");
return true;
}
public function Delete(string $name, string $user) : bool {
$this->LonaDB->Logger->Table("(".$this->file.") User '".$user."' is trying to delete the variable '".$name."'");
//Check if the executing user has write permissions on this table
if(!$this->CheckPermission($user, "write")) return false;
//Delete the variable and save
unset($this->data[$name]);
$this->Save();
$this->LonaDB->Logger->Table("(".$this->file.") User '".$user."' deleted the variable '".$name."'");
return true;
}
public function Get(string $name, string $user) : mixed {
$this->LonaDB->Logger->Table("(".$this->file.") User '".$user."' is trying to get the variable '".$name."'");
//Check if the executing user has read permissions on this table
if(!$this->CheckPermission($user, "read")) return null;
//Return variable's value
return $this->data[$name];
}
public function CheckPermission(string $user, string $permission) : bool {
//Check if the user is the table owner
if($user === $this->Owner) return true;
//Check if the user is an Administrator or Superuser
if($this->LonaDB->UserManager->GetRole($user) === "Administrator" || $this->LonaDB->UserManager->GetRole($user) === "Superuser") return true;
//Check if the user is an table Administrator
if($this->permissions[$user]["admin"]) return true;
//Check if the user doesn't have the permission
if(!$this->permissions[$user][$permission]) return false;
//All checks have been run and the user has the permission
//Return true
return true;
}
public function CheckVariable(string $name, string $user) : bool {
//Check if the executing user has read permissions on this table
if(!$this->CheckPermission($user, 'read')) return false;
//Check if variable exists and return state
if(!$this->data[$name]) return false;
return true;
}
public function AddPermission(string $name, string $permission, string $user) : bool {
if($user !== $this->Owner && !$this->permissions[$user]["admin"]) {
$this->LonaDB->Logger->Table("(".$this->file.") Missing permission! Adding permission '".$permission."' for user '".$name."', requested by '".$user."'");
return false;
}
if($user !== $this->Owner && $permission === "admin") {
$this->LonaDB->Logger->Table("(".$this->file.") Not the Owner! Adding permission '".$permission."' for user '".$name."', requested by '".$user."'");
return false;
}
$this->LonaDB->Logger->Table("(".$this->file.") Adding permission '".$permission."' for user '".$name."', requested by '".$user."'");
//Check if user is table owner/administrator, global administrator or superuser
if($user !== $this->Owner && !$this->permissions[$user]["admin"] && $this->LonaDB->UserManager->GetRole($user) !== "Administrator" && $this->LonaDB->UserManager->GetRole($user) !== "Superuser") return false;
//Add permission and save
$this->permissions[$name][$permission] = true;
$this->Save();
return true;
}
public function RemovePermission(string $name, string $permission, string $user) : bool {
if($user !== $this->Owner && !$this->permissions[$user]["admin"]) {
$this->LonaDB->Logger->Table("(".$this->file.") Missing permission! Removing permission '".$permission."' for user '".$name."', requested by '".$user."'");
return false;
}
if($user !== $this->Owner && $permission === "admin") {
$this->LonaDB->Logger->Table("(".$this->file.") Not the Owner! Removing permission '".$permission."' for user '".$name."', requested by '".$user."'");
return galse;
}
$this->LonaDB->Logger->Table("(".$this->file.") Removing permission '".$permission."' for user '".$name."', requested by '".$user."'");
//Check if user is table owner/administrator, global administrator or superuser
if($user !== $this->Owner && !$this->permissions[$user]["admin"] && $this->LonaDB->UserManager->GetRole($user) !== "Administrator" && $this->LonaDB->UserManager->GetRole($user) !== "Superuser") return false;
//Remove permission and save
unset($this->permissions[$name][$permission]);
if($this->permissions[$name] === array()) unset($this->permissions[$name]);
$this->Save();
}
private function Save() : void {
//Generate IV and array to save
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(AES_256_CBC));
$save = array(
"data" => $this->data,
@ -153,7 +149,9 @@ class Table{
"owner" => $this->Owner
);
//Encrypt array using IV
$encrypted = openssl_encrypt(json_encode($save), AES_256_CBC, $this->LonaDB->config["encryptionKey"], 0, $iv);
//Save encrypted array and IV
file_put_contents("./data/tables/".$this->file.".lona", $encrypted.":".base64_encode($iv));
}
}

View File

@ -2,83 +2,98 @@
namespace LonaDB\Tables;
//Load autoload from composer
require 'vendor/autoload.php';
//Load Main file
use LonaDB\LonaDB;
class TableManager{
//Create all variables
private LonaDB $LonaDB;
private array $Tables;
public function __construct(LonaDB $lonaDB){
$this->LonaDB = $lonaDB;
//Initialize tables array
$this->Tables = array();
//Check if directory "data/tables/" exists, create if it doesn't
if(!is_dir("data/")) mkdir("data/");
if(!is_dir("data/tables/")) mkdir("data/tables/");
//Counter variable for counting tables and creating the Default table if none exist
$counter = 0;
//For all files and folders in "data/tables/"
foreach (new \DirectoryIterator('data/tables') as $fileInfo) {
//Check if file extension is ".lona"
if(str_ends_with($fileInfo->getFilename(), ".lona")){
//Initialize table instance
$this->Tables[substr($fileInfo->getFilename(), 0, -5)] = new Table($this->LonaDB, false, $fileInfo->getFilename());
//Count up
$counter = $counter + 1;
}
}
//No table files exist
if($counter === 0){
//Create default table
$this->CreateTable("Default", "root");
}
}
public function GetTable(string $name) : mixed {
//Check if table exists
if(!$this->Tables[$name]) return false;
//Return table instance
return $this->Tables[$name];
}
public function ListTables(string $user = "") : array {
//Temporary array of tables to return
$tables = array();
//Check if there is a certain user we want the tables for
if($user !== ""){
//Loop through all tables
foreach($this->Tables as $table){
//Check if the user has read or write permissions on the table => Push the table to the array
if($table->CheckPermission($user, "write")) array_push($tables, $table->Name);
else if($table->CheckPermission($user, "read")) array_push($tables, $table->Name);
}
}
else{
//Loop through all tables
foreach($this->Tables as $table){
//Add the table to the array
array_push($tables, $table->Name);
}
}
//Return temporary tables array
return $tables;
}
public function CreateTable(string $name, string $owner) : bool {
$this->LonaDB->Logger->Table("Trying to create table '" . $name . "', owned by user '" . $owner . "'");
if($this->Tables[$name]) {
$this->LonaDB->Logger->Error("Table '" . $name . "' already exists");
return false;
}
//Check if there already is a table with the exact same name
if($this->Tables[$name]) return false;
//Create table instance
$this->Tables[$name] = new Table($this->LonaDB, true, $name, $owner);
$this->LonaDB->Logger->Table("Table '" . $name . "' has been created");
return true;
}
public function DeleteTable(string $name, string $user) : bool {
$this->LonaDB->Logger->Table("Trying to delete table '" . $name . "', requested by user '" . $user . "'");
if(!$this->Tables[$name]) {
$this->LonaDB->Logger->Error("Table '" . $name . "' doesn't exist");
return false;
}
//Check if the table exists
if(!$this->Tables[$name]) return false;
if($user !== $this->Tables[$name]->GetOwner() && $this->LonaDB->UserManager->GetRole($user) !== "Administrator" && $this->LonaDB->UserManager->GetRole($user) !== "Superuser") {
$this->LonaDB->Logger->Table("Not the owner! Trying to delete table '" . $name . "', requested by user '" . $user . "'");
return false;
}
//Check if deleting user is the table owner, a global administrator or superuser
if($user !== $this->Tables[$name]->GetOwner() && $this->LonaDB->UserManager->GetRole($user) !== "Administrator" && $this->LonaDB->UserManager->GetRole($user) !== "Superuser") return false;
//Delete table file and instance from the tables array
unlink("data/tables/".$name.".lona");
unset($this->Tables[$name]);
$this->LonaDB->Logger->Table("Deleted table '" . $name . "', requested by user '" . $user . "'");
return true;
}
}