diff --git a/workflow/engine/methods/setup/pluginsChange.php b/workflow/engine/methods/setup/pluginsChange.php index ff3ccd5db..f51c1b16a 100644 --- a/workflow/engine/methods/setup/pluginsChange.php +++ b/workflow/engine/methods/setup/pluginsChange.php @@ -7,43 +7,91 @@ * @link https://wiki.processmaker.com/3.0/Plugins#Enable_and_Disable_a_Plugin */ -// lets display the items use ProcessMaker\Plugins\PluginRegistry; -$pluginFile = $_GET['id']; -$pluginStatus = $_GET['status']; +function handlePluginChange() { + try { + // Validar parĂ¡metros de entrada + if (!isset($_GET['id']) || !isset($_GET['status'])) { + throw new InvalidArgumentException('Missing required parameters'); + } -$items = array (); -//here we are enabling or disabling the plugin and all related options registered. -$filter = new InputFilter(); -$path = PATH_PLUGINS . $pluginFile; -$path = $filter->validateInput($path, 'path'); + $pluginFile = $_GET['id']; + $pluginStatus = $_GET['status']; -$oPluginRegistry = PluginRegistry::loadSingleton(); + // Validar formato del archivo de plugin + if (!preg_match('/^[a-zA-Z0-9_-]+\.php$/', $pluginFile)) { + throw new InvalidArgumentException('Invalid plugin file format'); + } -if ($handle = opendir(PATH_PLUGINS)) { - while (false !== ($file = readdir($handle))) { - if (strpos($file, '.php', 1) && $file == $pluginFile) { - if ($pluginStatus == '1') { - // change to disable - $details = $oPluginRegistry->getPluginDetails($pluginFile); + // Validar status + if (!in_array($pluginStatus, ['0', '1'], true)) { + throw new InvalidArgumentException('Invalid plugin status'); + } + + // Sanitizar nombre del plugin + $pluginName = basename(str_replace(".php", "", $pluginFile)); + + if (!preg_match('/^[a-zA-Z0-9_-]+$/', $pluginName)) { + throw new InvalidArgumentException('Invalid plugin name format'); + } + + // Validar rutas de forma segura + $pluginFilePath = realpath(PATH_PLUGINS . $pluginFile); + $pluginDirPath = realpath(PATH_PLUGINS . $pluginName); + $pluginsDir = realpath(PATH_PLUGINS); + + if (!$pluginFilePath || strpos($pluginFilePath, $pluginsDir) !== 0) { + throw new SecurityException('Plugin file outside allowed directory'); + } + + if (!is_file($pluginFilePath)) { + throw new FileNotFoundException('Plugin file not found'); + } + + $oPluginRegistry = PluginRegistry::loadSingleton(); + + if ($pluginStatus === '1') { + // Deshabilitar plugin + $details = $oPluginRegistry->getPluginDetails($pluginFile); + if ($details) { $oPluginRegistry->disablePlugin($details->getNamespace()); $oPluginRegistry->savePlugin($details->getNamespace()); G::auditLog("DisablePlugin", "Plugin Name: " . $details->getNamespace()); - } else { - $pluginName = str_replace(".php", "", $pluginFile); - - if (is_file(PATH_PLUGINS . $pluginName . ".php") && is_dir(PATH_PLUGINS . $pluginName)) { - // change to ENABLED - require_once($path); - $details = $oPluginRegistry->getPluginDetails($pluginFile); + return ['success' => true, 'action' => 'disabled', 'plugin' => $details->getNamespace()]; + } + } else { + // Habilitar plugin + if ($pluginDirPath && is_dir($pluginDirPath)) { + require_once($pluginFilePath); + $details = $oPluginRegistry->getPluginDetails($pluginFile); + if ($details) { $oPluginRegistry->enablePlugin($details->getNamespace()); - $oPluginRegistry->setupPlugins(); //get and setup enabled plugins + $oPluginRegistry->setupPlugins(); $oPluginRegistry->savePlugin($details->getNamespace()); G::auditLog("EnablePlugin", "Plugin Name: " . $details->getNamespace()); + return ['success' => true, 'action' => 'enabled', 'plugin' => $details->getNamespace()]; } + } else { + throw new FileNotFoundException('Plugin directory not found'); } } + + return ['success' => false, 'error' => 'Plugin operation failed']; + + } catch (Exception $e) { + G::auditLog('PluginChange', 'Error: ' . $e->getMessage()); + return ['success' => false, 'error' => $e->getMessage()]; } - closedir($handle); } + +// Ejecutar y devolver respuesta JSON +try { + $result = handlePluginChange(); + header('Content-Type: application/json'); + echo json_encode($result); +} catch (Exception $e) { + header('Content-Type: application/json'); + http_response_code(400); + echo json_encode(['success' => false, 'error' => 'Invalid request']); +} \ No newline at end of file diff --git a/workflow/engine/plugins/.gitignore b/workflow/engine/plugins/.gitignore deleted file mode 100644 index e69de29bb..000000000