| JSON_HEX_AMP // &
| JSON_HEX_APOS // ‘
| JSON_HEX_QUOT // ”
);
}
// 1) ここでだけ判定・処理。出力はまだしない!
//if ($_SERVER[‘REQUEST_METHOD’] !== ‘POST’) {
// http_response_code(405);
// header(‘Allow: POST’);
// exit; // ここで終了 → HTMLは出ない
//}
$cfg = json_decode(file_get_contents(__DIR__.’/config.json’), true) ?? [];
$pid = null;
$doc = realpath($_SERVER[‘DOCUMENT_ROOT’] ?? ”);
if (array_key_exists(‘pid’, $_POST)) {
$pid = trim((string)$_POST[‘pid’]);
} elseif (array_key_exists(‘pid’, $_GET)) {
$pid = trim((string)$_GET[‘pid’]);
}
$pid = trim((string)$pid);
// 1) 空や不正文字を即エラー
if ($pid === ” || !preg_match(‘/\A[a-zA-Z0-9_-]+\z/’, $pid)) {
render_error();
}
$fno = null;
if (array_key_exists(‘fno’, $_POST)) {
$fno = trim((string)$_POST[‘fno’]);
} elseif (array_key_exists(‘fno’, $_GET)) {
$fno = trim((string)$_GET[‘fno’]);
}
$boot = array_merge($cfg, [‘pid’ => $pid,’fno’ => $fno]);
// 2) ベースディレクトリ
$base = realpath($doc. $boot[“baseRoot”]);
$iconRoot = realpath($doc. $boot[“iconRoot”]);
$hotspotFs = realpath($iconRoot.”/hotspot3.png”);
$hotspotUrl = ‘data:image/png;base64,’ . base64_encode(file_get_contents($hotspotFs));
if ($base === false) {
render_error();
}
// 3) 実在確認 + ディレクトリ脱出防止(realpath で正規化 → prefixチェック)
$path = $base . DIRECTORY_SEPARATOR . $pid;
if ($path === false || strncmp($path, $base, strlen($base)) !== 0 || !is_dir($path)) {
render_error();
}
// 4) 検証OK → セッションへ格納して次の処理へ
$_SESSION[‘pid’] = $pid;
// AI画像の検出とJSONの書き換えはあれば行うようにする
$ai_path = __DIR__ . ‘/ai_json_write.php’;
// Warningを出したくなければ file_exists で事前チェック
if (file_exists($ai_path)) {
include_once $ai_path;
}
if (function_exists(‘ai_json_write’)) {
ai_json_write($path);
}
// 2) ここから初めてHTMLを出力(テンプレート読込)
header(‘Cache-Control: no-store’);
?>