$ErrorActionPreference = 'Stop' $projectRoot = Split-Path -Parent $PSScriptRoot $workPath = Join-Path $projectRoot ('temp\template-flow-' + [guid]::NewGuid().ToString('N')) $templateRoot = Join-Path $workPath 'templates' $assetRoot = Join-Path $templateRoot 'images' $databasePath = Join-Path $workPath 'test.mdb' $configPath = Join-Path $workPath 'test.ini' $previewRoot = Join-Path $workPath 'previews' $templatePath = Join-Path $templateRoot 'postcard.html' $imagePath = Join-Path $assetRoot 'logo.png' $scriptHost = Join-Path $env:SystemRoot 'SysWOW64\cscript.exe' $powerShellX86 = Join-Path $env:SystemRoot 'SysWOW64\WindowsPowerShell\v1.0\powershell.exe' try { $null = New-Item -ItemType Directory -Path $assetRoot -Force $example = Get-Content -LiteralPath (Join-Path $projectRoot 'config.example.ini') -Raw $example.Replace('DB_PATH=data/MassMailer.mdb', ('DB_PATH=' + $databasePath)).Replace( 'TEMPLATE_ROOT=templates', ('TEMPLATE_ROOT=' + $templateRoot)) | Set-Content -LiteralPath $configPath -Encoding UTF8 & $scriptHost //nologo (Join-Path $PSScriptRoot 'init-db.vbs') $configPath if ($LASTEXITCODE -ne 0) { throw 'MDB initialization failed' } $png = [Convert]::FromBase64String('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+jRZkAAAAASUVORK5CYII=') [System.IO.File]::WriteAllBytes($imagePath, $png) $safe = '

Postcard

See our offer.

LogoDetails' [System.IO.File]::WriteAllText($templatePath, $safe, [System.Text.Encoding]::UTF8) & $powerShellX86 -NoProfile -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot 'import-template.ps1') -Path $templatePath -ConfigPath $configPath if ($LASTEXITCODE -ne 0) { throw 'Valid template import failed' } Remove-Item -LiteralPath $imagePath -Force $preview = & $powerShellX86 -NoProfile -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot 'preview-template.ps1') -TemplateId 1 -ConfigPath $configPath -OutputRoot $previewRoot if ($LASTEXITCODE -ne 0 -or -not (Test-Path -LiteralPath $preview -PathType Leaf)) { throw 'Snapshot preview failed after source image deletion' } $rendered = Get-Content -LiteralPath $preview -Raw if ($rendered -notmatch 'image-1.png' -or $rendered -match 'cid:|file:|See our offer.

', ''), $safe.Replace('images/logo.png', '../secret.png'), $safe.Replace('color:#112233', 'background-image:url(file:///C:/secret)'), $safe.Replace('http://example.invalid', 'javascript:alert(1)') )) { [System.IO.File]::WriteAllText($templatePath, $invalid, [System.Text.Encoding]::UTF8) $ErrorActionPreference = 'Continue' $null = & $powerShellX86 -NoProfile -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot 'import-template.ps1') -Path $templatePath -ConfigPath $configPath 2>$null $rejected = $LASTEXITCODE -ne 0 $ErrorActionPreference = 'Stop' if (-not $rejected) { throw 'Unsafe template was accepted' } } & $powerShellX86 -NoProfile -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot 'test-template-state.ps1') -ConfigPath $configPath if ($LASTEXITCODE -ne 0) { throw 'Invalid imports changed the template library' } Write-Output 'Template import, image snapshot, safe preview, and rejection checks passed' } finally { $resolvedWork = [System.IO.Path]::GetFullPath($workPath) $resolvedTemp = [System.IO.Path]::GetFullPath((Join-Path $projectRoot 'temp')) if ($resolvedWork.StartsWith($resolvedTemp + [System.IO.Path]::DirectorySeparatorChar, [StringComparison]::OrdinalIgnoreCase) -and (Test-Path -LiteralPath $resolvedWork)) { Remove-Item -LiteralPath $resolvedWork -Recurse -Force } }