108 lines
3.9 KiB
PHP
Executable File
108 lines
3.9 KiB
PHP
Executable File
<?php
|
|
// Patch l99-chat.php avec pattern SSE mémoire
|
|
// Doctrine 146 : SSE memory via curl WRITEFUNCTION hook + shutdown
|
|
// Non-invasif : intercepte les chunks, save à la fin
|
|
|
|
header('Content-Type: application/json');
|
|
|
|
$target = '/var/www/html/api/l99-chat.php';
|
|
$backup = '/var/www/html/vault-gold/opus/l99-chat-doctrine146-' . date('Ymd-His') . '.bak';
|
|
|
|
if (!file_exists($target)) { echo json_encode(['ok'=>false,'err'=>'not found']); exit; }
|
|
|
|
// Check chattr
|
|
$attr = shell_exec("lsattr $target 2>&1");
|
|
if (strpos($attr, '----i') !== false) {
|
|
shell_exec("sudo chattr -i $target 2>/dev/null");
|
|
}
|
|
|
|
@mkdir(dirname($backup), 0755, true);
|
|
copy($target, $backup);
|
|
|
|
$content = file_get_contents($target);
|
|
|
|
if (strpos($content, 'DOCTRINE-146-SSE') !== false) {
|
|
echo json_encode(['ok'=>false, 'err'=>'already patched']);
|
|
exit;
|
|
}
|
|
|
|
// Injection 1 : après auth check ($q parsing), avant $env load
|
|
// Cherche: "if(!$q){echo"
|
|
$anchor1 = '$env=[];';
|
|
$inject1 = '// === DOCTRINE-146-SSE · memory bridge SSE pattern ===
|
|
if (@file_exists(__DIR__.\'/wevia-memory-bridge.php\')) { @require_once __DIR__.\'/wevia-memory-bridge.php\'; }
|
|
$__chat_id = \'l99-chat\';
|
|
$__user_id = $_GET[\'user_id\'] ?? $_COOKIE[\'weval_chat_session\'] ?? (\'anon-\'.substr(md5(($_SERVER[\'REMOTE_ADDR\']??\'\').($_SERVER[\'HTTP_USER_AGENT\']??\'\')),0,12));
|
|
$__sse_accumulator = \'\';
|
|
register_shutdown_function(function() use (&$__sse_accumulator, $__chat_id, $__user_id, $q) {
|
|
if (!function_exists(\'wevia_mem_save\')) return;
|
|
// Parse SSE chunks - extract content from data: lines
|
|
$parsed = \'\';
|
|
foreach (explode("\n", $__sse_accumulator) as $line) {
|
|
if (strpos($line, \'data: \') !== 0) continue;
|
|
$json = substr($line, 6);
|
|
if ($json === \'[DONE]\') continue;
|
|
$d = @json_decode($json, true);
|
|
// OpenAI style
|
|
if (isset($d[\'choices\'][0][\'delta\'][\'content\'])) {
|
|
$parsed .= $d[\'choices\'][0][\'delta\'][\'content\'];
|
|
}
|
|
// Custom style {t: ...}
|
|
elseif (isset($d[\'t\']) && is_string($d[\'t\'])) {
|
|
$parsed .= $d[\'t\'];
|
|
}
|
|
}
|
|
if ($parsed && $q) {
|
|
@wevia_mem_save($__chat_id, $__user_id, $q, substr($parsed, 0, 4000), \'internal\');
|
|
}
|
|
});
|
|
// === /DOCTRINE-146-SSE ===
|
|
|
|
' . $anchor1;
|
|
|
|
if (strpos($content, $anchor1) === false) {
|
|
shell_exec("sudo chattr +i $target 2>/dev/null");
|
|
echo json_encode(['ok'=>false, 'err'=>'anchor1 not found']);
|
|
exit;
|
|
}
|
|
$content = str_replace($anchor1, $inject1, $content);
|
|
|
|
// Injection 2 : hook CURLOPT_WRITEFUNCTION pour accumuler
|
|
// Cherche: "CURLOPT_WRITEFUNCTION=>function($c,$d)use($p){"
|
|
$anchor2 = 'CURLOPT_WRITEFUNCTION=>function($c,$d)use($p){';
|
|
$inject2 = 'CURLOPT_WRITEFUNCTION=>function($c,$d)use($p,&$GLOBALS){
|
|
$GLOBALS[\'__sse_accumulator\'] = ($GLOBALS[\'__sse_accumulator\'] ?? \'\') . $d;';
|
|
|
|
if (strpos($content, $anchor2) === false) {
|
|
// Try relaxed version
|
|
$relax_match = preg_match('/CURLOPT_WRITEFUNCTION\s*=>\s*function\s*\(\s*\$c\s*,\s*\$d\s*\)\s*use\s*\(\s*\$p\s*\)\s*\{/', $content);
|
|
shell_exec("sudo chattr +i $target 2>/dev/null");
|
|
echo json_encode(['ok'=>false, 'err'=>'anchor2 not found', 'relax_match'=>$relax_match]);
|
|
exit;
|
|
}
|
|
$content = str_replace($anchor2, $inject2, $content);
|
|
|
|
// Lint
|
|
$tmp = tempnam('/tmp', 'l99-sse-');
|
|
file_put_contents($tmp, $content);
|
|
$lint = shell_exec("php -l $tmp 2>&1");
|
|
if (strpos($lint, 'No syntax errors') === false) {
|
|
unlink($tmp);
|
|
shell_exec("sudo chattr +i $target 2>/dev/null");
|
|
echo json_encode(['ok'=>false, 'err'=>'lint fail', 'lint'=>$lint]);
|
|
exit;
|
|
}
|
|
|
|
file_put_contents($target, $content);
|
|
shell_exec("sudo chown www-data:www-data $target");
|
|
shell_exec("sudo chattr +i $target 2>/dev/null");
|
|
unlink($tmp);
|
|
@opcache_reset();
|
|
|
|
echo json_encode([
|
|
'ok' => true,
|
|
'backup' => $backup,
|
|
'patches' => ['shutdown_function', 'writefunction_hook'],
|
|
'ts' => date('c')
|
|
]);
|