Plugin sync

This commit is contained in:
fbsanchez 2021-06-16 15:53:05 +02:00
parent 841842da59
commit b701b2be32
3 changed files with 543 additions and 381 deletions

View File

@ -26,6 +26,9 @@
* ============================================================================
*/
use PandoraFMS\Enterprise\Metaconsole\Synchronizer;
use PandoraFMS\Tools\Files;
// Load global vars.
global $config;
@ -115,53 +118,50 @@ echo $output;
$zip = null;
$upload = false;
if (isset($_FILES['plugin_upload']) === true) {
$config['plugin_store'] = $config['attachment_store'].'/plugin';
$basepath = $config['attachment_store'].'/plugin';
$name_file = $_FILES['plugin_upload']['name'];
$filename = $_FILES['plugin_upload']['name'];
$uploaded_filename = $_FILES['plugin_upload']['tmp_name'];
$zip = zip_open($_FILES['plugin_upload']['tmp_name']);
$upload = true;
$tmp_path = Files::tempdirnam(
$config['attachment_store'].'/downloads/',
'plugin_uploaded_'
);
if ($tmp_path === false) {
$error = __('Failed to create temporary directory');
}
if (isset($zip) === true && empty($zip) === false) {
while ($zip_entry = zip_read($zip)) {
if (zip_entry_open($zip, $zip_entry, 'r')) {
if (zip_entry_name($zip_entry) == 'plugin_definition.ini') {
$basepath = $config['attachment_store'];
} else {
$basepath = $config['plugin_store'];
$error = '';
}
$filename = $basepath.'/'.zip_entry_name($zip_entry);
$fp = fopen($filename, 'w');
$buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
fwrite($fp, $buf);
fclose($fp);
chmod($filename, 0755);
zip_entry_close($zip_entry);
}
}
if ($error === null) {
if (Files::unzip($uploaded_filename, $tmp_path) === true) {
// Successfully extracted to tmp directory.
// Grant execution over all files found.
Files::chmod($tmp_path, 0755);
zip_close($zip);
}
// Operate.
$ini_array = parse_ini_file($tmp_path.'/plugin_definition.ini', true);
// Clean plugin_definition.ini file.
unlink($tmp_path.'/plugin_definition.ini');
if ($upload === true) {
$ini_array = parse_ini_file($config['attachment_store'].'/plugin_definition.ini', true);
// Parse with sections.
if ($ini_array === false) {
ui_print_error_message(__('Cannot load INI file'));
$error = __('Cannot load INI file');
} else {
$version = preg_replace('/.*[.]/', '', $name_file);
$exec_path = $config['plugin_store'].'/'.$ini_array['plugin_definition']['filename'];
// Relocate files to target destination.
Files::move($tmp_path.'/*', $basepath.'/', true);
// Extract information.
$version = preg_replace('/.*[.]/', '', $filename);
$exec_path = $basepath.'/'.$ini_array['plugin_definition']['filename'];
$file_exec_path = $exec_path;
if (isset($ini_array['plugin_definition']['execution_command']) === true
&& empty($ini_array['plugin_definition']['execution_command']) === false
) {
$exec_path = $ini_array['plugin_definition']['execution_command'];
$exec_path .= ' '.$config['plugin_store'].'/';
$exec_path .= ' '.$basepath.'/';
$exec_path .= $ini_array['plugin_definition']['filename'];
}
@ -172,20 +172,18 @@ if ($upload === true) {
}
if (file_exists($file_exec_path) === false) {
ui_print_error_message(__('Plugin exec not found. Aborting!'));
$error = __('Plugin exec not found. Aborting!');
unlink($config['attachment_store'].'/plugin_definition.ini');
} else {
// Verify if a plugin with the same name is already registered.
$sql = sprintf(
'SELECT COUNT(*)
FROM tplugin
WHERE name = "%s"',
'SELECT COUNT(*) FROM tplugin WHERE name = "%s"',
io_safe_input($ini_array['plugin_definition']['name'])
);
$result = db_get_sql($sql);
if ($result > 0) {
ui_print_error_message(__('Plugin already registered. Aborting!'));
$error = __('Plugin already registered. Aborting!');
unlink($config['attachment_store'].'/plugin_definition.ini');
} else {
$values = [
@ -508,6 +506,59 @@ if ($upload === true) {
}
}
}
// Clean.
Files::rmrf($tmp_path);
} else {
$error = __('Unable to uncompress uploaded file');
}
}
if (file_exists($uploaded_filename) === true) {
if (is_metaconsole() === true && is_management_allowed() === true) {
// Keep uploaded file to be transferred to nodes.
if (is_dir($config['attachment_store'].'/downloads/') === false) {
mkdir($config['attachment_store'].'/downloads/');
}
$keep = move_uploaded_file(
$uploaded_filename,
$config['attachment_store'].'/downloads/'.$filename
);
if ($keep === false) {
$error = __(
'Cannot move uploaded file to %s.',
$config['attachment_store'].'/downloads/'
);
}
} else {
// Clean temporary files.
unlink($uploaded_filename);
}
}
if ($error !== null && $error !== '') {
ui_print_error_message($error);
} else if (is_management_allowed() === true && is_metaconsole() === true) {
$attachment = '/'.str_replace(
$config['homedir'],
'',
$config['attachment_store']
);
$sc = new Synchronizer();
$sc->queueOperation(
Synchronizer::OPERATION_REFRESH_PLUGIN,
ui_get_full_url(
$attachment.'/downloads/'.$filename,
false,
false,
false
)
);
}
if (is_metaconsole() === true) {

View File

@ -26,6 +26,7 @@
* ============================================================================
*/
// Get global data.
// Constants.
define('MIME_UNKNOWN', 0);
@ -120,6 +121,8 @@ if (function_exists('mime_content_type') === false) {
global $config;
require_once $config['homedir'].'/vendor/autoload.php';
/**
* Upload file.
@ -197,38 +200,27 @@ function upload_file($upload_file_or_zip, $default_real_directory)
// Upload zip.
if ($upload_zip === true) {
if (isset($_FILES['file']) === true && empty($_FILES['file']['name']) === false) {
if (isset($_FILES['file']) === true
&& empty($_FILES['file']['name']) === false
) {
$filename = $_FILES['file']['name'];
$filesize = $_FILES['file']['size'];
$filepath = $_FILES['file']['tmp_name'];
$real_directory = filemanager_safe_directory((string) get_parameter('real_directory'));
$directory = filemanager_safe_directory((string) get_parameter('directory'));
if (strpos($real_directory, $default_real_directory) !== 0) {
// Perform security check to determine whether received upload directory is part of the default path for caller uploader and user is not trying to access an external path (avoid execution of PHP files in directories that are not explicitly controlled by corresponding .htaccess).
// Perform security check to determine whether received upload
// directory is part of the default path for caller uploader
// and user is not trying to access an external path (avoid
// execution of PHP files in directories that are not explicitly
// controlled by corresponding .htaccess).
ui_print_error_message(__('Security error'));
} else {
// Copy file to directory and change name.
if (empty($directory) === true) {
$nombre_archivo = $real_directory.'/'.$filename;
if (PandoraFMS\Tools\Files::unzip($filepath, $real_directory) === false) {
ui_print_error_message(__('No he podido descomprimir tu archivo de mierda'));
} else {
$nombre_archivo = $homedir_filemanager.'/'.$directory.'/'.$filename;
}
if (! @copy($_FILES['file']['tmp_name'], $nombre_archivo)) {
ui_print_error_message(__('Attach error'));
} else {
// Delete temporal file.
unlink($_FILES['file']['tmp_name']);
// Extract the zip file.
$zip = new ZipArchive;
$pathname = $homedir_filemanager.'/'.$directory.'/';
if ($zip->open($nombre_archivo) === true) {
$zip->extractTo($pathname);
unlink($nombre_archivo);
}
ui_print_success_message(__('Upload correct'));
$config['filemanager']['correct_upload_file'] = 1;
}

View File

@ -194,4 +194,123 @@ class Files
}
/**
* Create a temporary directory with unique name.
*
* @param string $directory The directory where the temporary filename will be created.
* @param string $prefix The prefix of the generated temporary filename.
* Windows use only the first three characters of prefix.
*
* @return string|false The new temporary filename, or false on failure.
*/
public static function tempdirnam(string $directory, string $prefix='')
{
$filename = tempnam($directory, $prefix);
if ($filename === false) {
return false;
}
if (file_exists($filename) === true) {
unlink($filename);
mkdir($filename);
if (is_dir($filename) === true && is_writable($filename) === true) {
return $filename;
}
}
return false;
}
/**
* Apply permissions recursively on path.
*
* @param string $path Path to a file or directory.
* @param integer $file_perms Permissions to be applied to files found.
* @param integer $dir_perms Permissions to be applied to directories found.
*
* @return void
*/
public static function chmod(
string $path,
int $file_perms=0644,
int $dir_perms=0755
) {
if (is_dir($path) === true) {
// Permissions over directories.
$dh = opendir($path);
if ($dh === false) {
return;
}
while (false !== ($fh = readdir($dh))) {
if (is_dir($fh) === true) {
if ($fh === '.' || $fh === '..') {
continue;
}
// Recursion: directory.
self::chmod($path.'/'.$fh, $file_perms, $dir_perms);
} else {
// Recursion: file.
self::chmod($path.'/'.$fh, $file_perms, $dir_perms);
}
}
closedir($dh);
} else {
// Permissions over files.
chmod($path, $file_perms);
}
}
/**
* Move from source to destination
*
* @param string $source Source (directory or file).
* @param string $destination Destination (directory).
* @param boolean $content_only Moves only content if directories.
*
* @return boolean True if success False if not.
*/
public static function move(
string $source,
string $destination,
bool $content_only=false
):bool {
if (is_dir($destination) === false
|| is_writable($destination) === false
) {
return false;
}
if (is_file($source) === true
|| (is_dir($source) === true && $content_only === false)
) {
return rename($source, $destination.'/'.basename($source));
}
// Dir, but content only.
if (is_dir($source) !== true || $content_only !== true) {
return false;
}
// Get array of all source files.
$files = scandir($source);
// Identify directories.
$source = $source.'/';
$destination = $destination.'/';
// Cycle through all source files.
foreach ($files as $file) {
if (in_array($file, ['.', '..']) === true) {
continue;
}
// If we copied this successfully, mark it for deletion.
rename($source.$file, $destination.$file);
}
}
}