Plugins and Functions

This commit is contained in:
Collin 2024-03-03 21:19:01 +00:00
parent 32b226bf41
commit 6cb356d3ef
12 changed files with 341 additions and 18 deletions

View File

@ -69,7 +69,7 @@ try {
builderLog("[INFO] Phar archive created successfully");
builderLog("[RUN] Generating run script");
file_put_contents("./build/run-phar.sh", 'cd '.$path.' ; printf "test\n" | php -dextension=openswoole.so '.$filename.'-'.$version.'.phar');
file_put_contents("./build/run-phar.sh", 'cd '.$path.' ; printf "test\n" | php -dextension=openswoole.so -dphar.readonly=0 '.$filename.'-'.$version.'.phar');
builderLog("[RUN] Adding Permissions to run script");
exec("chmod 777 ./build/run-phar.sh");

View File

@ -1 +1 @@
cd build/release ; printf "test\n" | php -dextension=openswoole.so LonaDB-4.0.0-stable.phar
cd build/release ; printf "test\n" | php -dextension=openswoole.so -dphar.readonly=0 LonaDB-4.3.0-stable.phar

View File

@ -1,6 +1,6 @@
{
"filename": "LonaDB",
"version": "4.0.0-stable",
"version": "4.3.0-stable",
"path": "build",
"debug": false
}

View File

@ -0,0 +1,18 @@
<?php
return new class {
public function run($LonaDB, $data, $server, $fd) : void {
if(!$LonaDB->UserManager->CheckPermission($data['login']['name'], "create_function")) {
$response = json_encode(["success" => false, "err" => "no_permission", "process" => $data['process']]);
$server->send($fd, $response);
$server->close($fd);
return;
}
$function = $LonaDB->FunctionManager->Create($data['function']['name'], $data['function']['content']);
$response = json_encode(["success" => true, "process" => $data['process']]);
$server->send($fd, $response);
$server->close($fd);
}
};

View File

@ -0,0 +1,18 @@
<?php
return new class {
public function run($LonaDB, $data, $server, $fd) : void {
if(!$LonaDB->UserManager->CheckPermission($data['login']['name'], "create_function")) {
$response = json_encode(["success" => false, "err" => "no_permission", "process" => $data['process']]);
$server->send($fd, $response);
$server->close($fd);
return;
}
$function = $LonaDB->FunctionManager->Delete($data['function']['name']);
$response = json_encode(["success" => true, "process" => $data['process']]);
$server->send($fd, $response);
$server->close($fd);
}
};

View File

@ -0,0 +1,9 @@
<?php
return new class {
public function run($LonaDB, $data, $server, $fd) : void {
$function = $LonaDB->FunctionManager->GetFunction($data['name']);
$function->Execute($LonaDB, $data, $server, $fd);
}
};

View File

@ -0,0 +1,55 @@
<?php
namespace LonaDB\Functions;
define('AES_256_CBC', 'aes-256-cbc');
require 'vendor/autoload.php';
use LonaDB\LonaDB;
use LonaDB\Functions\LonaFunction;
class FunctionManager{
private LonaDB $LonaDB;
private array $Functions;
public function __construct(LonaDB $lonaDB){
$this->LonaDB = $lonaDB;
$this->Functions = array();
if(!is_dir("data/")) mkdir("data/");
if(!is_dir("data/functions/")) mkdir("data/functions/");
foreach (new \DirectoryIterator('data/functions') as $fileInfo) {
if(str_ends_with($fileInfo->getFilename(), ".lona")){
$this->Functions[substr($fileInfo->getFilename(), 0, -5)] = new LonaFunction($this->LonaDB, $fileInfo->getFilename());
}
}
}
public function GetFunction(string $name) : mixed {
if(!$this->Functions[$name]) return false;
return $this->Functions[$name];
}
public function Create(string $name, string $content) : bool {
if($this->Functions[$name]) return false;
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(AES_256_CBC));
$encrypted = openssl_encrypt(json_encode($content), AES_256_CBC, $this->LonaDB->config["encryptionKey"], 0, $iv);
file_put_contents("./data/functions/".$name.".lona", $encrypted.":".base64_encode($iv));
$this->Functions[$name] = new LonaFunction($this->LonaDB, $name . ".lona");
return true;
}
public function Delete(string $name) : bool {
if(!$this->Functions[$name]) return false;
unset($this->Functions[$name]);
unlink("./data/functions/".$name.".lona");
return true;
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace LonaDB\Functions;
define('AES_256_CBC', 'aes-256-cbc');
use LonaDB\LonaDB;
class LonaFunction{
private string $file;
public string $Name;
private array $data;
private LonaDB $LonaDB;
public function __construct(LonaDB $lonaDB, string $name){
$this->LonaDB = $lonaDB;
$this->LonaDB->Logger->Load("Trying to load function '".$name."'");
$parts = explode(':', file_get_contents("./data/functions/".$name));
$temp = json_decode(openssl_decrypt($parts[0], AES_256_CBC, $this->LonaDB->config["encryptionKey"], 0, base64_decode($parts[1])), true);
$this->file = substr($name, 0, -5);
$this->Name = $this->file;
$function = "\$this->data['" . $this->Name . "'] = new class {\n";
$function .= "public function run(\$LonaDB, \$data, \$server, \$fd) {\n";
$function .= $temp;
$function .= "\n} \n};";
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);
}
}

View File

@ -9,25 +9,23 @@ use LonaDB\Server;
use LonaDB\Logger;
use LonaDB\Tables\TableManager;
use LonaDB\Users\UserManager;
use LonaDB\Functions\FunctionManager;
use LonaDB\Plugins\PluginManager;
class LonaDB {
public array $config;
private bool $Running = true;
public string $EncryptionKey;
public Logger $Logger;
public Server $Server;
public TableManager $TableManager;
public UserManager $UserManager;
public FunctionManager $FunctionManager;
public PluginManager $PluginManager;
public function __construct() {
echo "Encryption key:\n";
$keyHandle = fopen ("php://stdin","r");
$key = fgets($keyHandle);
fclose($keyHandle);
$this->EncryptionKey = str_replace("\n","",$key);
unset($key);
public function __construct(string $key) {
$this->EncryptionKey = $key;
$this->Logger = new Logger($this);
try{
@ -36,7 +34,6 @@ class LonaDB {
$this->Logger->InfoCache("Looking for config.");
//somehow file_exists() always retuns false for me... But this checks if the file did exist in the first place.
file_put_contents("configuration.lona", file_get_contents("configuration.lona"));
if(file_get_contents("configuration.lona") === "") $this->setup();
@ -66,14 +63,58 @@ class LonaDB {
$this->TableManager = new TableManager($this);
$this->Logger->Info("Loading UserManager class.");
$this->UserManager = new UserManager($this);
$this->Logger->Info("Loading Server class.");
$this->Server = new Server($this);
$this->Logger->Info("Loading FunctionManager class.");
$this->FunctionManager = new FunctionManager($this);
$this->Logger->Info("Loading PluginManager class.");
$this->PluginManager = new PluginManager($this);
$pid = @ pcntl_fork();
if( $pid == -1 ) {
throw new Exception( $this->getError( Thread::COULD_NOT_FORK ), Thread::COULD_NOT_FORK );
}
if( $pid ) {
// parent
$this->pid = $pid;
}
else {
$this->PluginManager->LoadPlugins();
}
$serverpid = @ pcntl_fork();
if( $serverpid == -1 ) {
throw new Exception( $this->getError( Thread::COULD_NOT_FORK ), Thread::COULD_NOT_FORK );
}
if( $serverpid ) {
// parent
$this->serverpid = $serverpid;
}
else {
$this->Logger->Info("Loading Server class.");
$this->Server = new Server($this);
}
while($this->Running){
}
}
catch (\Exception $e){
$this->Logger->Error($e);
}
}
private function Load() : void {
$pid = @ pcntl_fork();
if( $pid == -1 ) {
throw new Exception( $this->getError( Thread::COULD_NOT_FORK ), Thread::COULD_NOT_FORK );
}
if( $pid ) {
$this->pid = $pid;
}
else {
}
}
private function setup() : void {
$this->Logger->InfoCache("Invalid or missing config. Starting setup.");
echo "Database port:\n";
@ -117,6 +158,21 @@ class LonaDB {
$encrypted = openssl_encrypt(json_encode($save), AES_256_CBC, $this->EncryptionKey, 0, $iv);
file_put_contents("./configuration.lona", $encrypted.":".base64_encode($iv));
}
public function Stop() : void {
posix_kill( $this->pid, SIGKILL );
posix_kill( $this->serverpid, SIGKILL );
$this->Running = false;
}
}
$run = new LonaDB();
echo "Encryption key:\n";
$keyHandle = fopen ("php://stdin","r");
$key = fgets($keyHandle);
fclose($keyHandle);
$encryptionKey = str_replace("\n","",$key);
unset($key);
$run = new LonaDB($encryptionKey);

View File

@ -0,0 +1,118 @@
<?php
namespace LonaDB\Plugins;
require 'vendor/autoload.php';
use LonaDB\LonaDB;
class PluginManager{
private LonaDB $LonaDB;
private array $Plugins;
private array $EnabledPlugins;
public function __construct(LonaDB $lonaDB) {
$this->LonaDB = $lonaDB;
$this->Tables = array();
}
public function LoadPlugins () : void {
if(!is_dir("plugins/")) mkdir("plugins/");
$results = scandir("plugins/");
foreach($results as $r){
if(str_ends_with($r, ".phar")){
$phar = new \Phar("plugins/" . $r, 0);
foreach (new \RecursiveIteratorIterator($phar) as $file) {
if($file->getFileName() === "plugin.json") {
$conf = json_decode(file_get_contents($file->getPathName()), true);
eval("\$path = substr(\$file->getPathName(), 0, -". strlen($file->getFileName()) .");");
}
}
if($conf['main'] && $conf['main']['path'] && $conf['main']['class'] && $conf['main']['namespace'] && $conf['name']){
file_put_contents($path . $conf['main']['path'], file_get_contents($path . $conf['main']['path']));
if(file_get_contents($path. $conf['main']['path']) !== ""){
try{
$this->load_classphp($path, $phar);
eval("\$this->Plugins[\$conf['name']] = new " . $conf['main']['namespace'] . "\\" . $conf['main']['class'] . "();");
$this->Plugins[$conf['name']]->onEnable($this->LonaDB);
}
catch(e){
$this->LonaDB->Logger->Error("Could not load main file for plugin '" . $conf['name'] . "'");
}
}
else $this->LonaDB->Logger->Error("Main file for plugin '" . $conf['name'] . "' is declared in config but doesn't exist");
}
else{
$this->LonaDB->Logger->Error("Could not load the plugin in '" . $r . "'");
}
}
else if($r != "." && $r !== ".."){
$debugscan = scandir("plugins/" . $r);
if(in_array("plugin.json", $debugscan)) $conf = json_decode(file_get_contents("plugins/" . $r . "/plugin.json"), true);
if($conf['main'] && $conf['main']['path'] && $conf['main']['class'] && $conf['main']['namespace'] && $conf['name']){
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{
$this->load_classphp("plugins/" . $r . "/");
if($conf['build']){
$phar = new \Phar("plugins/".$conf['name']."-".$conf['version'].".phar", 0, "plugins/".$conf['name']."-".$conf['version'].".phar");
$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();
}
eval("\$this->Plugins[\$conf['name']] = new " . $conf['main']['namespace'] . "\\" . $conf['main']['class'] . "();");
$this->Plugins[$conf['name']]->onEnable($this->LonaDB);
}
catch(e){
$this->LonaDB->Logger->Error("Could not load main file for plugin '" . $conf['name'] . "'");
}
}
else $this->LonaDB->Logger->Error("Main file for plugin '" . $conf['name'] . "' is declared in config but doesn't exist");
}
else{
$this->LonaDB->Logger->Error("Could not load the plugin in '" . $r . "'");
}
}
}
}
public function GetPlugin(string $name) : mixed {
if($this->Plugins[$name]) return $this->Plugins[$name];
else return false;
}
private function load_classphp(string $path, \Phar $phar = null) : void {
if(str_starts_with($path, "phar")){
foreach (new \RecursiveIteratorIterator($phar) as $file) {
if(str_ends_with($file->getPathName(), ".php")) require_once $file->getPathName();
}
}
if(str_ends_with($path, "/")) $path = substr($path, 0, -1);
$items = glob( $path . "/*" );
foreach( $items as $item ) {
$isPhp = str_ends_with($item, ".php");
if ( $isPhp ) {
require_once $item;
} else{
$this->load_classphp( $item . "/" );
}
}
}
}

View File

@ -50,7 +50,16 @@ class Server {
$this->handleData($data, $server, $fd);
});
$this->server->start();
try{
$this->server->start();
}
catch(e){
$this->LonaDB->Logger->Error(e);
}
}
public function Stop() : void {
$this->server->stop();
}
private function handleData(string $dataString, TCPServer $server, int $fd) : void {

View File

@ -146,7 +146,7 @@ class Table{
$this->Save();
}
private function Save(){
private function Save() : void {
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(AES_256_CBC));
$save = array(
"data" => $this->data,