Simplifies the rename done in ce3979d : PS_Launcher.exe is the only
name. Removes the dual-path lookup in LauncherSelfUpdater, the
duplicated taskkill blocks in the .bat scripts, the legacy patterns
in .gitignore, and the explanatory comments about the migration.
Cleaner code, single source of truth for the binary name.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
198 lines
8.5 KiB
PHP
198 lines
8.5 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
require __DIR__ . '/lib/Auth.php';
|
|
require __DIR__ . '/lib/Layout.php';
|
|
|
|
use PSLauncher\Admin\Auth;
|
|
use PSLauncher\Admin\Layout;
|
|
|
|
Auth::requireLogin();
|
|
$config = require __DIR__ . '/../api/config.php';
|
|
|
|
$root = dirname(__DIR__);
|
|
$manifestPath = "$root/manifest/versions.json";
|
|
$buildsDir = "$root/builds";
|
|
|
|
$message = null; $messageType = 'success';
|
|
|
|
function loadManifest(string $path): array
|
|
{
|
|
if (!is_file($path)) return ['schemaVersion' => 1, 'versions' => []];
|
|
return json_decode(file_get_contents($path), true) ?? [];
|
|
}
|
|
|
|
function saveManifest(string $path, array $manifest): void
|
|
{
|
|
// usort attend une référence — on ne peut pas lui passer `?? []` en PHP 8.
|
|
if (isset($manifest['versions']) && is_array($manifest['versions'])) {
|
|
usort($manifest['versions'], fn($a, $b) => version_compare($b['version'], $a['version']));
|
|
}
|
|
file_put_contents(
|
|
$path,
|
|
json_encode($manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n"
|
|
);
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
Auth::checkCsrf();
|
|
$action = $_POST['action'] ?? '';
|
|
$manifest = loadManifest($manifestPath);
|
|
|
|
try {
|
|
if ($action === 'set_launcher') {
|
|
$lver = trim($_POST['launcher_version'] ?? '');
|
|
$lmin = trim($_POST['launcher_min_required'] ?? '');
|
|
if (!preg_match('/^\d+\.\d+\.\d+$/', $lver)) {
|
|
throw new Exception('Numéro de version launcher invalide (X.Y.Z attendu).');
|
|
}
|
|
if ($lmin !== '' && !preg_match('/^\d+\.\d+\.\d+$/', $lmin)) {
|
|
throw new Exception('Numéro de version "minRequired" invalide.');
|
|
}
|
|
$base = $config['base_url'] ?? 'https://asterionvr.com/PS_Launcher';
|
|
$manifest['launcher'] = [
|
|
'version' => $lver,
|
|
'minRequired' => $lmin !== '' ? $lmin : '0.5.0',
|
|
'download' => [
|
|
'url' => "{$base}/builds/launcher/PS_Launcher-{$lver}.exe",
|
|
'sizeBytes' => 0,
|
|
'sha256' => 'REPLACE_AFTER_BUILD',
|
|
],
|
|
'releaseNotesUrl' => null,
|
|
];
|
|
saveManifest($manifestPath, $manifest);
|
|
$message = "Section launcher mise à jour (v{$lver}). Upload PS_Launcher-{$lver}.exe dans builds/launcher/ puis clique « Hasher le launcher + signer ».";
|
|
}
|
|
elseif ($action === 'remove_launcher') {
|
|
unset($manifest['launcher']);
|
|
saveManifest($manifestPath, $manifest);
|
|
$message = "Section launcher retirée du manifest (auto-update désactivé).";
|
|
}
|
|
elseif ($action === 'sync_launcher') {
|
|
require_once "$root/tools/SignManifest.php";
|
|
$signer = new \PSLauncher\Tools\SignManifest($root);
|
|
$force = !empty($_POST['force']);
|
|
$result = $signer->run('launcher', $force);
|
|
$forceLabel = $force ? ' [FORCE: cache ignoré]' : '';
|
|
$message = "Sortie du script (scope: launcher{$forceLabel}) :\n" . implode("\n", $result['log']);
|
|
if (!$result['ok']) $messageType = 'error';
|
|
}
|
|
} catch (Exception $e) {
|
|
$message = $e->getMessage();
|
|
$messageType = 'error';
|
|
}
|
|
}
|
|
|
|
$manifest = loadManifest($manifestPath);
|
|
$launcher = $manifest['launcher'] ?? null;
|
|
$launcherFiles = is_dir("$buildsDir/launcher")
|
|
? array_map('basename', glob("$buildsDir/launcher/*.exe") ?: [])
|
|
: [];
|
|
|
|
$launcherZipPresent = false;
|
|
$launcherHashed = false;
|
|
if ($launcher) {
|
|
$expectedFile = basename(parse_url($launcher['download']['url'] ?? '', PHP_URL_PATH) ?? '');
|
|
$launcherZipPresent = in_array($expectedFile, $launcherFiles, true);
|
|
$launcherHashed = !empty($launcher['download']['sha256'])
|
|
&& !str_starts_with($launcher['download']['sha256'], 'REPLACE');
|
|
}
|
|
|
|
Layout::header('Launcher', 'launcher');
|
|
?>
|
|
<h1>Launcher — auto-update</h1>
|
|
|
|
<?php Layout::flash($message, $messageType); ?>
|
|
|
|
<div class="card">
|
|
<h2>État actuel</h2>
|
|
<?php if ($launcher): ?>
|
|
<p>
|
|
Version annoncée : <strong>v<?= htmlspecialchars($launcher['version']) ?></strong>
|
|
• minRequired : <code><?= htmlspecialchars($launcher['minRequired'] ?? '—') ?></code>
|
|
• Exe : <?= $launcherZipPresent
|
|
? "<span class='badge badge-success'>présent</span>"
|
|
: "<span class='badge badge-warning'>absent</span>" ?>
|
|
• Hash : <?= $launcherHashed
|
|
? "<span class='badge badge-success'>OK</span>"
|
|
: "<span class='badge badge-warning'>à calculer</span>" ?>
|
|
• Signature manifest : <?= empty($manifest['signature'])
|
|
? "<span class='badge badge-warning'>NON SIGNÉ</span>"
|
|
: "<span class='badge badge-success'>SIGNÉ Ed25519</span>" ?>
|
|
</p>
|
|
<p class="muted">URL attendue de l'exe : <code><?= htmlspecialchars($launcher['download']['url']) ?></code></p>
|
|
<?php else: ?>
|
|
<p class="muted">Aucune version du launcher déclarée — l'auto-update est désactivé. Configure-la ci-dessous pour l'activer.</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Workflow d'une nouvelle version du launcher</h2>
|
|
<ol class="muted">
|
|
<li>Remplis le formulaire <strong>Définir / mettre à jour</strong> ci-dessous (ex : <code>0.6.0</code>).</li>
|
|
<li>Sur ton poste : <code>dotnet publish src\PSLauncher.App -c Release</code> et <code>dotnet publish src\PSLauncher.Updater -c Release</code> (les exes sont copiés à la racine du repo).</li>
|
|
<li>Renomme la copie : <code>PS_Launcher.exe → PS_Launcher-X.Y.Z.exe</code>.</li>
|
|
<li>Upload via SFTP dans <code>www/PS_Launcher/builds/launcher/</code>.</li>
|
|
<li>Clique <strong>🔁 Hasher le launcher + signer</strong>.</li>
|
|
<li>Les launchers déjà déployés détecteront la nouvelle version au prochain « Vérifier les MAJ ».</li>
|
|
</ol>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Définir / mettre à jour</h2>
|
|
<form method="post">
|
|
<?= Layout::csrfField() ?>
|
|
<input type="hidden" name="action" value="set_launcher">
|
|
<div class="row">
|
|
<div class="col field">
|
|
<label>Version launcher (X.Y.Z)</label>
|
|
<input type="text" name="launcher_version" placeholder="0.6.0"
|
|
value="<?= htmlspecialchars($launcher['version'] ?? '') ?>" required pattern="\d+\.\d+\.\d+">
|
|
</div>
|
|
<div class="col field">
|
|
<label>Version minimale requise (X.Y.Z)</label>
|
|
<input type="text" name="launcher_min_required" placeholder="0.5.0"
|
|
value="<?= htmlspecialchars($launcher['minRequired'] ?? '0.5.0') ?>" pattern="\d+\.\d+\.\d+">
|
|
</div>
|
|
</div>
|
|
<button class="btn btn-success" type="submit">Définir</button>
|
|
</form>
|
|
|
|
<form method="post" style="margin-top: 16px;">
|
|
<?= Layout::csrfField() ?>
|
|
<input type="hidden" name="action" value="sync_launcher">
|
|
<button class="btn btn-primary" type="submit">🔁 Hasher le launcher + signer</button>
|
|
<label style="margin-left:12px;font-size:12px;color:#888" title="Recalcule le SHA-256 même si l'exe n'a pas changé.">
|
|
<input type="checkbox" name="force" value="1"> Force re-hash
|
|
</label>
|
|
</form>
|
|
|
|
<?php if ($launcher): ?>
|
|
<form method="post" style="margin-top: 16px;"
|
|
onsubmit="return confirm('Retirer la section launcher du manifest ? L\'auto-update sera désactivé.')">
|
|
<?= Layout::csrfField() ?>
|
|
<input type="hidden" name="action" value="remove_launcher">
|
|
<button class="btn btn-danger" type="submit">Retirer la section launcher</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Exes présents dans builds/launcher/</h2>
|
|
<?php if (empty($launcherFiles)): ?>
|
|
<p class="muted">Aucun exe pour l'instant. Upload les binaires via SFTP dans <code>www/PS_Launcher/builds/launcher/</code>.</p>
|
|
<?php else: ?>
|
|
<table>
|
|
<thead><tr><th>Fichier</th><th>Taille</th></tr></thead>
|
|
<tbody>
|
|
<?php foreach ($launcherFiles as $f): ?>
|
|
<tr>
|
|
<td><code><?= htmlspecialchars($f) ?></code></td>
|
|
<td class="muted"><?= Layout::formatBytes(filesize("$buildsDir/launcher/$f")) ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php Layout::footer();
|