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

View File

@ -8,6 +8,8 @@ _admin();
$ui->assign('_title', $_L['Plugin Manager']); $ui->assign('_title', $_L['Plugin Manager']);
$ui->assign('_system_menu', 'settings'); $ui->assign('_system_menu', 'settings');
$plugin_repository = 'https://hotspotbilling.github.io/Plugin-Repository/repository.json';
$action = $routes['1']; $action = $routes['1'];
$admin = Admin::_info(); $admin = Admin::_info();
$ui->assign('_admin', $admin); $ui->assign('_admin', $admin);
@ -17,16 +19,105 @@ if ($admin['user_type'] != 'Admin') {
r2(U . "dashboard", 'e', $_L['Do_Not_Access']); 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) { switch ($action) {
default: case 'install':
$cache = 'system/cache/plugin_repository.json'; if(!is_writeable(File::pathFixer('system/cache/'))){
if (file_exists($cache) && time() - filemtime($cache) > (24 * 60 * 60)) { r2(U . "pluginmanager", 'e', 'Folder system/cache/ is not writable');
$json = json_decode(file_get_contents($cache), true);
} }
$data = file_get_contents('https://hotspotbilling.github.io/Plugin-Repository/repository.json'); if(!is_writeable(File::pathFixer('system/plugin/'))){
file_put_contents($cache, $data); r2(U . "pluginmanager", 'e', 'Folder system/plugin/ is not writable');
$json = json_decode($data, true); }
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('plugins', $json['plugins']);
$ui->assign('pgs', $json['payment_gateway']); $ui->assign('pgs', $json['payment_gateway']);
$ui->display('plugin-manager.tpl'); $ui->display('plugin-manager.tpl');

View File

@ -17,7 +17,11 @@
class="btn btn-primary"><i class="ion ion-chatboxes"></i> Website</a> class="btn btn-primary"><i class="ion ion-chatboxes"></i> Website</a>
<a href="{$plugin['github']}" target="_blank" <a href="{$plugin['github']}" target="_blank"
class="btn btn-success"><i class="ion ion-chatboxes"></i> Github</a> 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> class="btn btn-warning"><i class="ion ion-chatboxes"></i> Install</a>
</div> </div>
</div> </div>
@ -42,7 +46,11 @@
class="btn btn-primary"><i class="ion ion-chatboxes"></i> Website</a> class="btn btn-primary"><i class="ion ion-chatboxes"></i> Website</a>
<a href="{$pg['github']}" target="_blank" <a href="{$pg['github']}" target="_blank"
class="btn btn-success"><i class="ion ion-chatboxes"></i> Github</a> 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> class="btn btn-warning"><i class="ion ion-chatboxes"></i> Install</a>
</div> </div>
</div> </div>