diff --git a/lib/updater.js b/lib/updater.js index 59be8ee..733084c 100644 --- a/lib/updater.js +++ b/lib/updater.js @@ -61,6 +61,10 @@ function findLatestYml(assets) { return assets.find(a => /^latest\.yml$/i.test(a.name)) || null; } +function normalizeInstallerName(value) { + return path.basename(String(value || '')).toLowerCase().replace(/[ ._]+/g, ''); +} + async function fetchJson(url, signal) { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), CHECK_TIMEOUT); @@ -180,7 +184,7 @@ async function parseLatestYml(url, expected = {}, fetchImpl = fetch) { if (expected.version && version !== expected.version) { throw new Error('Prüfsummen-Metadaten gehören zu einer anderen Version'); } - if (expected.assetName && path.basename(assetPath) !== path.basename(expected.assetName)) { + if (expected.assetName && normalizeInstallerName(assetPath) !== normalizeInstallerName(expected.assetName)) { throw new Error('Prüfsummen-Metadaten gehören nicht zum ausgewählten Installer'); } if (expected.assetSize && size !== Number(expected.assetSize)) { diff --git a/tests/updater-version.test.js b/tests/updater-version.test.js index f73b715..2db6d33 100644 --- a/tests/updater-version.test.js +++ b/tests/updater-version.test.js @@ -336,3 +336,18 @@ test('existing release recovery rejects a mismatched transport tag', async () => /existing release tag "v9\.9\.9" does not match "v2\.1\.20"/ ); }); + +test('checksum metadata accepts equivalent transport-specific installer separators', async () => { + const sha = crypto.randomBytes(64).toString('base64'); + const metadata = await parseLatestYml('https://update.invalid/latest.yml', { + version: '2.1.22', + assetName: 'Multi-Hoster-Upload Setup 2.1.22.exe', + assetSize: 456 + }, async () => ({ + ok: true, + status: 200, + text: async () => `version: 2.1.22\npath: Multi-Hoster-Upload.Setup.2.1.22.exe\nsha512: ${sha}\nsize: 456\n` + })); + + assert.equal(metadata.path, 'Multi-Hoster-Upload.Setup.2.1.22.exe'); +});