plugin manager

This commit is contained in:
Ibnu Maksum 2023-03-08 11:08:56 +07:00
parent 2155c3adae
commit b0542ab8be
No known key found for this signature in database
GPG Key ID: 7FC82848810579E5
5 changed files with 231 additions and 53 deletions

View File

@ -3,7 +3,7 @@
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
**/
Class App{
class App{
public static function _run(){
return true;
}

56
system/autoload/File.php Normal file
View File

@ -0,0 +1,56 @@
<?php
class File
{
public static function copyFolder($from, $to, $exclude = [])
{
echo "copyFolder($from, $to);<br>";
$files = scandir($from);
print_r($files);
foreach ($files as $file) {
if (is_file($from . $file) && !in_array($file, $exclude)) {
if (file_exists($to . $file)) unlink($to . $file);
rename($from . $file, $to . $file);
echo "rename($from$file, $to$file);<br>";
} else if (is_dir($from . $file) && !in_array($file, ['.', '..'])) {
if (!file_exists($to . $file)) {
echo "mkdir($to$file);;<br>";
mkdir($to . $file);
}
echo "File::copyFolder($from$file, $to$file);<br>";
File::copyFolder($from . $file . DIRECTORY_SEPARATOR, $to . $file . DIRECTORY_SEPARATOR);
}
}
}
public static function deleteFolder($path)
{
$files = scandir($path);
foreach ($files as $file) {
if (is_file($path . $file)) {
echo "unlink($path$file);<br>";
unlink($path . $file);
} else if (is_dir($path . $file) && !in_array($file, ['.', '..'])) {
File::deleteFolder($path . $file . DIRECTORY_SEPARATOR);
echo "rmdir($path$file);<br>";
rmdir($path . $file);
}
}
echo "rmdir($path);<br>";
rmdir($path);
}
/**
* file path fixer
*
* @access public
* @param string $path
* @return string
*/
public static function pathFixer($path)
{
return str_replace("/", DIRECTORY_SEPARATOR, $path);
}
}

View File

@ -1,12 +1,14 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
**/
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
**/
/**
* Validator class
*/
class Validator{
class Validator
{
/**
* String text finder
@ -16,14 +18,15 @@ class Validator{
* @param array $hits
* @return void
*/
private static function textHit($string, $exclude=""){
if(empty($exclude)) return false;
if(is_array($exclude)){
foreach($exclude as $text){
if(strstr($string, $text)) return true;
private static function textHit($string, $exclude = "")
{
if (empty($exclude)) return false;
if (is_array($exclude)) {
foreach ($exclude as $text) {
if (strstr($string, $text)) return true;
}
}else{
if(strstr($string, $exclude)) return true;
} else {
if (strstr($string, $exclude)) return true;
}
return false;
}
@ -37,9 +40,10 @@ class Validator{
* @param int $min
* @return bool
*/
private static function numberBetween($integer, $max=null, $min=0){
if(is_numeric($min) && $integer <= $min) return false;
if(is_numeric($max) && $integer >= $max) return false;
private static function numberBetween($integer, $max = null, $min = 0)
{
if (is_numeric($min) && $integer <= $min) return false;
if (is_numeric($max) && $integer >= $max) return false;
return true;
}
@ -51,8 +55,9 @@ class Validator{
* @param array $exclude
* @return bool
*/
public static function Email($string, $exclude=""){
if(self::textHit($string, $exclude)) return false;
public static function Email($string, $exclude = "")
{
if (self::textHit($string, $exclude)) return false;
return (bool)preg_match("/^([a-z0-9])(([-a-z0-9._])*([a-z0-9]))*\@([a-z0-9])(([a-z0-9-])*([a-z0-9]))+(\.([a-z0-9])([-a-z0-9_-])?([a-z0-9])+)+$/i", $string);
}
@ -63,8 +68,9 @@ class Validator{
* @param strin $string
* @return bool
*/
public static function Url($string, $exclude=""){
if(self::textHit($string, $exclude)) return false;
public static function Url($string, $exclude = "")
{
if (self::textHit($string, $exclude)) return false;
return (bool)preg_match("/^(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i", $string);
}
@ -75,7 +81,8 @@ class Validator{
* @param string $string
* @return void
*/
public static function Ip($string){
public static function Ip($string)
{
return (bool)preg_match("/^(1?\d{1,2}|2([0-4]\d|5[0-5]))(\.(1?\d{1,2}|2([0-4]\d|5[0-5]))){3}$/", $string);
}
@ -88,9 +95,10 @@ class Validator{
* @param int $min
* @return bool
*/
public static function Number($integer, $max=null, $min=0){
if(preg_match("/^\-?\+?[0-9e1-9]+$/",$integer)){
if(!self::numberBetween($integer, $max, $min)) return false;
public static function Number($integer, $max = null, $min = 0)
{
if (preg_match("/^\-?\+?[0-9e1-9]+$/", $integer)) {
if (!self::numberBetween($integer, $max, $min)) return false;
return true;
}
return false;
@ -103,8 +111,9 @@ class Validator{
* @param int $integer
* @return bool
*/
public static function UnsignedNumber($integer){
return (bool)preg_match("/^\+?[0-9]+$/",$integer);
public static function UnsignedNumber($integer)
{
return (bool)preg_match("/^\+?[0-9]+$/", $integer);
}
/**
@ -114,8 +123,9 @@ class Validator{
* @param string $string
* @return bool
*/
public static function Float($string){
return (bool)($string==strval(floatval($string)))? true : false;
public static function Float($string)
{
return (bool)($string == strval(floatval($string))) ? true : false;
}
/**
@ -125,7 +135,8 @@ class Validator{
* @param string $string
* @return void
*/
public static function Alpha($string){
public static function Alpha($string)
{
return (bool)preg_match("/^[a-zA-Z]+$/", $string);
}
@ -136,7 +147,8 @@ class Validator{
* @param string $string
* @return void
*/
public static function AlphaNumeric($string){
public static function AlphaNumeric($string)
{
return (bool)preg_match("/^[0-9a-zA-Z]+$/", $string);
}
@ -148,7 +160,8 @@ class Validator{
* @param array $allowed
* @return void
*/
public static function Chars($string, $allowed=array("a-z")){
public static function Chars($string, $allowed = array("a-z"))
{
return (bool)preg_match("/^[" . implode("", $allowed) . "]+$/", $string);
}
@ -161,9 +174,10 @@ class Validator{
* @param int $min
* @return bool
*/
public static function Length($string, $max=null, $min=0){
public static function Length($string, $max = null, $min = 0)
{
$length = strlen($string);
if(!self::numberBetween($length, $max, $min)) return false;
if (!self::numberBetween($length, $max, $min)) return false;
return true;
}
@ -174,7 +188,8 @@ class Validator{
* @param string $string
* @return void
*/
public static function HexColor($string){
public static function HexColor($string)
{
return (bool)preg_match("/^(#)?([0-9a-f]{1,2}){3}$/i", $string);
}
@ -191,7 +206,8 @@ class Validator{
* @param string $string
* @return bool
*/
public static function Date($string){
public static function Date($string)
{
$date = date('Y', strtotime($string));
return ($date == "1970" || $date == '') ? false : true;
}
@ -204,9 +220,10 @@ class Validator{
* @param int $age
* @return bool
*/
public static function OlderThan($string, $age){
public static function OlderThan($string, $age)
{
$date = date('Y', strtotime($string));
if($date == "1970" || $date == '') return false;
if ($date == "1970" || $date == '') return false;
return (date('Y') - $date) > $age ? true : false;
}
@ -217,7 +234,8 @@ class Validator{
* @param string $string
* @return bool
*/
public static function Xml($string){
public static function Xml($string)
{
$Xml = @simplexml_load_string($string);
return ($Xml === false) ? false : true;
}
@ -231,7 +249,8 @@ class Validator{
* @param int $min
* @return bool
*/
public static function FilesizeBetween($file, $max=null, $min=0){
public static function FilesizeBetween($file, $max = null, $min = 0)
{
$filesize = filesize($file);
return self::numberBetween($filesize, $max, $min);
}
@ -247,10 +266,11 @@ class Validator{
* @param int $min_height
* @return void
*/
public static function ImageSizeBetween($image, $max_width="", $min_width=0, $max_height="", $min_height=0){
public static function ImageSizeBetween($image, $max_width = "", $min_width = 0, $max_height = "", $min_height = 0)
{
$size = getimagesize($image);
if(!self::numberBetween($size[0], $max_width, $min_width)) return false;
if(!self::numberBetween($size[1], $max_height, $min_height)) return false;
if (!self::numberBetween($size[0], $max_width, $min_width)) return false;
if (!self::numberBetween($size[1], $max_height, $min_height)) return false;
return true;
}
@ -261,8 +281,10 @@ class Validator{
* @param string $phone
* @return bool
*/
public static function Phone($phone){
$formats = array( '###-###-####',
public static function Phone($phone)
{
$formats = array(
'###-###-####',
'####-###-###',
'(###) ###-###',
'####-####-####',
@ -271,7 +293,8 @@ class Validator{
'###-###-###',
'#####-###-###',
'##########',
'####-##-##-##');
'####-##-##-##'
);
$format = trim(preg_replace("/[0-9]/", "#", $phone));
return (bool)in_array($format, $formats);
}

View File

@ -8,6 +8,8 @@ _admin();
$ui->assign('_title', $_L['Plugin Manager']);
$ui->assign('_system_menu', 'settings');
$plugin_repository = 'https://hotspotbilling.github.io/Plugin-Repository/repository.json';
$action = $routes['1'];
$admin = Admin::_info();
$ui->assign('_admin', $admin);
@ -17,16 +19,105 @@ if ($admin['user_type'] != 'Admin') {
r2(U . "dashboard", 'e', $_L['Do_Not_Access']);
}
$cache = File::pathFixer('system/cache/plugin_repository.json');
if (file_exists($cache) && time() - filemtime($cache) > (24 * 60 * 60)) {
$json = json_decode(file_get_contents($cache), true);
} else {
$data = file_get_contents($plugin_repository);
file_put_contents($cache, $data);
$json = json_decode($data, true);
}
switch ($action) {
default:
$cache = 'system/cache/plugin_repository.json';
if (file_exists($cache) && time() - filemtime($cache) > (24 * 60 * 60)) {
$json = json_decode(file_get_contents($cache), true);
case 'install':
if(!is_writeable(File::pathFixer('system/cache/'))){
r2(U . "pluginmanager", 'e', 'Folder system/cache/ is not writable');
}
$data = file_get_contents('https://hotspotbilling.github.io/Plugin-Repository/repository.json');
file_put_contents($cache, $data);
$json = json_decode($data, true);
if(!is_writeable(File::pathFixer('system/plugin/'))){
r2(U . "pluginmanager", 'e', 'Folder system/plugin/ is not writable');
}
set_time_limit(-1);
$tipe = $routes['2'];
$plugin = $routes['3'];
$file = File::pathFixer('system/cache/') . $plugin . '.zip';
if (file_exists($file)) unlink($file);
if ($tipe == 'plugin') {
foreach ($json['plugins'] as $plg) {
if ($plg['id'] == $plugin) {
$fp = fopen($file, 'w+');
$ch = curl_init($plg['github'].'/archive/refs/heads/master.zip');
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_exec($ch);
curl_close($ch);
fclose($fp);
$zip = new ZipArchive();
$zip->open($file);
$zip->extractTo(File::pathFixer('system/cache/'));
$zip->close();
$folder = File::pathFixer('system/cache/' . $plugin.'-main/');
if(!file_exists($folder)){
$folder = File::pathFixer('system/cache/' . $plugin.'-master/');
}
if(!file_exists($folder)){
r2(U . "pluginmanager", 'e', 'Extracted Folder is unknown');
}
File::copyFolder($folder, File::pathFixer('system/plugin/'), ['README.md','LICENSE']);
File::deleteFolder($folder);
unlink($file);
r2(U . "pluginmanager", 's', 'Plugin '.$plugin.' has been installed');
break;
}
}
break;
} else if ($tipe == 'payment') {
foreach ($json['payment_gateway'] as $plg) {
if ($plg['id'] == $plugin) {
$fp = fopen($file, 'w+');
$ch = curl_init($plg['github'].'/archive/refs/heads/master.zip');
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_exec($ch);
curl_close($ch);
fclose($fp);
$zip = new ZipArchive();
$zip->open($file);
$zip->extractTo(File::pathFixer('system/cache/'));
$zip->close();
$folder = File::pathFixer('system/cache/' . $plugin.'-main/');
if(!file_exists($folder)){
$folder = File::pathFixer('system/cache/' . $plugin.'-master/');
}
if(!file_exists($folder)){
r2(U . "pluginmanager", 'e', 'Extracted Folder is unknown');
}
File::copyFolder($folder, File::pathFixer('system/paymentgateway/'), ['README.md','LICENSE']);
File::deleteFolder($folder);
unlink($file);
r2(U . "paymentgateway", 's', 'Payment Gateway '.$plugin.' has been installed');
break;
}
}
break;
}
default:
if (class_exists('ZipArchive')) {
$zipExt = true;
} else {
$zipExt = false;
}
$ui->assign('zipExt', $zipExt);
$ui->assign('plugins', $json['plugins']);
$ui->assign('pgs', $json['payment_gateway']);
$ui->display('plugin-manager.tpl');

View File

@ -17,7 +17,11 @@
class="btn btn-primary"><i class="ion ion-chatboxes"></i> Website</a>
<a href="{$plugin['github']}" target="_blank"
class="btn btn-success"><i class="ion ion-chatboxes"></i> Github</a>
<a href="{$_url}pluginmanager/?install={$plugin['id']}"
<a {if $zipExt }
href="{$_url}pluginmanager/install/plugin/{$plugin['id']}" onclick="return confirm('Installing plugin will take some time to complete, do not close the page while it loading to install the plugin')"
{else}
href="#" onclick="alert('PHP ZIP extension is not available')"
{/if}
class="btn btn-warning"><i class="ion ion-chatboxes"></i> Install</a>
</div>
</div>
@ -42,7 +46,11 @@
class="btn btn-primary"><i class="ion ion-chatboxes"></i> Website</a>
<a href="{$pg['github']}" target="_blank"
class="btn btn-success"><i class="ion ion-chatboxes"></i> Github</a>
<a href="{$_url}pluginmanager/?install={$pg['id']}"
<a {if $zipExt }
href="{$_url}pluginmanager/install/payment/{$pg['id']}" onclick="return confirm('Installing plugin will take some time to complete, do not close the page while it loading to install the plugin')"
{else}
href="#" onclick="alert('PHP ZIP extension is not available')"
{/if}
class="btn btn-warning"><i class="ion ion-chatboxes"></i> Install</a>
</div>
</div>