fix(plugins): red de seguridad ante exit() en un gancho y globales del CMS
Tras la revision de codigo de 273c3dd:
- Un exit()/die() dentro de un gancho no es una excepcion y dejaba un cuerpo
que no era JSON. register_shutdown_function en _pluginLifecycle responde
{ok:false, error, messages:[lo impreso]} si el gancho no llego al final.
- event/plugin/origin se castean solo si son escalares (un array producia un
Warning delante del JSON).
- Los ganchos ven CURRENT_USER, menu, action, TABLE_PREFIX y SETTINGS como
un checkpoint desde addPlugins(); documentado en el contrato.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HPL66q9F33YZxbLPUT7KW8
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
3565abdd88
commit
ea8eb6dbcb
@@ -412,15 +412,32 @@ function _pluginLifecycle() {
|
||||
// respeta ficheros personalizados y puede haber entregado este y no aquel.
|
||||
die(json_encode(["ok" => false, "error" => "El cargador de plugins de esta web no soporta ganchos (cms/lib/plugins/index.php desactualizado)"]));
|
||||
}
|
||||
$event = (string) @$datos["event"];
|
||||
$plugin = (string) @$datos["plugin"];
|
||||
// Red de seguridad: exit()/die() dentro de un gancho no es una excepcion y
|
||||
// se saltaria el die(json_encode(...)) de abajo dejando un cuerpo que no es
|
||||
// JSON. Si al cerrar no hemos respondido, respondemos nosotros.
|
||||
$GLOBALS["_pluginLifecycleRespondido"] = false;
|
||||
register_shutdown_function(function () {
|
||||
if (!empty($GLOBALS["_pluginLifecycleRespondido"])) return;
|
||||
$salida = "";
|
||||
while (ob_get_level() > 0) { $salida .= (string) ob_get_clean(); }
|
||||
echo json_encode(array(
|
||||
"ok" => false,
|
||||
"error" => "El gancho ha terminado con exit()/die() sin devolver resultado",
|
||||
"messages" => $salida !== "" ? array(trim($salida)) : array(),
|
||||
));
|
||||
});
|
||||
$event = is_scalar(@$datos["event"]) ? (string) $datos["event"] : "";
|
||||
$plugin = is_scalar(@$datos["plugin"]) ? (string) $datos["plugin"] : "";
|
||||
$origin = is_scalar(@$datos["origin"]) ? (string) $datos["origin"] : "";
|
||||
$context = array(
|
||||
"origin" => in_array(@$datos["origin"], array("forge", "legacy"), true) ? $datos["origin"] : "desconocido",
|
||||
"origin" => in_array($origin, array("forge", "legacy"), true) ? $origin : "desconocido",
|
||||
"dropData" => filter_var(@$datos["dropData"], FILTER_VALIDATE_BOOLEAN),
|
||||
// Misma señal de entorno que header.php: el .acai solo existe en las copias locales.
|
||||
"mode" => file_exists(__DIR__ . "/../../../.acai") ? "local" : "production",
|
||||
);
|
||||
die(json_encode(runPluginLifecycle($plugin, $event, $context)));
|
||||
$resultado = runPluginLifecycle($plugin, $event, $context);
|
||||
$GLOBALS["_pluginLifecycleRespondido"] = true;
|
||||
die(json_encode($resultado));
|
||||
}
|
||||
|
||||
function _removeFileRutaSegura($ruta, $esPlugin) {
|
||||
|
||||
Reference in New Issue
Block a user