import { createHash } from 'node:crypto'; import { mkdtempSync, writeFileSync, rmSync, mkdirSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { execFileSync } from 'node:child_process'; const url = 'https://hyperos.mi.com/font-download/MiSans.zip'; const sha256 = 'b6aa1fc827035922612df8edf36e5609bca1c5441e25cd57572204569b7b81d9'; const weights = ['Thin', 'ExtraLight', 'Light', 'Normal', 'Regular', 'Medium', 'Demibold', 'Semibold', 'Bold', 'Heavy']; const destination = '/usr/local/share/fonts/misans'; const temporary = mkdtempSync(join(tmpdir(), 'misans-')); try { const response = await fetch(url, { signal: AbortSignal.timeout(300000) }); if (!response.ok) throw new Error(`MiSans download failed: ${response.status}`); const archive = Buffer.from(await response.arrayBuffer()); if (createHash('sha256').update(archive).digest('hex') !== sha256) { throw new Error('MiSans archive checksum mismatch; review upstream changes before updating'); } const archivePath = join(temporary, 'MiSans.zip'); writeFileSync(archivePath, archive); mkdirSync(destination, { recursive: true }); for (const weight of weights) { const name = `MiSans-${weight}.ttf`; // Extract only fixed, reviewed filenames; never unpack arbitrary archive paths. const font = execFileSync('python3', ['-c', 'import sys, zipfile; sys.stdout.buffer.write(zipfile.ZipFile(sys.argv[1]).read(sys.argv[2]))', archivePath, `MiSans/ttf/${name}`], { maxBuffer: 16000000 }); writeFileSync(join(destination, name), font, { mode: 0o644 }); } execFileSync('fc-cache', ['-f', destination], { stdio: 'inherit' }); const family = execFileSync('fc-match', ['-f', '%{family}', 'MiSans'], { encoding: 'utf8' }); if (!family.split(',').includes('MiSans')) throw new Error(`MiSans font lookup failed: ${family}`); } finally { rmSync(temporary, { recursive: true, force: true }); }