Files

137 lines
5.6 KiB
PowerShell

[CmdletBinding()]
param(
[switch]$NoLaunch,
[switch]$SkipShortcuts,
[switch]$SkipProcessCheck,
[string]$InstallRoot = '',
[string]$RoamingRoot = '',
[string]$LocalRoot = ''
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
function Copy-Tree {
param(
[Parameter(Mandatory = $true)][string]$Source,
[Parameter(Mandatory = $true)][string]$Destination
)
if (-not (Test-Path -LiteralPath $Source -PathType Container)) {
throw "Required source directory is missing: $Source"
}
New-Item -ItemType Directory -Path $Destination -Force | Out-Null
& robocopy.exe $Source $Destination /E /COPY:DAT /DCOPY:DAT /R:2 /W:1 /XJ /NFL /NDL /NP
$code = $LASTEXITCODE
if ($code -gt 7) {
throw "Copy failed with robocopy exit code $code ($Source)"
}
}
function Move-ToBackup {
param([Parameter(Mandatory = $true)][string]$Path)
if (-not (Test-Path -LiteralPath $Path)) {
return $null
}
$parent = Split-Path -Parent $Path
$leaf = Split-Path -Leaf $Path
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$suffix = [Guid]::NewGuid().ToString('N').Substring(0, 6)
$backup = Join-Path $parent ($leaf + '.backup-' + $stamp + '-' + $suffix)
Move-Item -LiteralPath $Path -Destination $backup
return $backup
}
$packageRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
$sourceApp = Join-Path $packageRoot 'App'
$sourceRoaming = Join-Path $packageRoot 'Seed\Roaming\BitBrowser'
$sourceLocal = Join-Path $packageRoot 'Seed\Local\BitBrowser'
$targetApp = if ($InstallRoot) { [System.IO.Path]::GetFullPath($InstallRoot) } else { Join-Path $env:LOCALAPPDATA 'Programs\BitBrowser' }
$targetRoaming = if ($RoamingRoot) { [System.IO.Path]::GetFullPath($RoamingRoot) } else { Join-Path $env:APPDATA 'BitBrowser' }
$targetLocal = if ($LocalRoot) { [System.IO.Path]::GetFullPath($LocalRoot) } else { Join-Path $env:LOCALAPPDATA 'BitBrowser' }
$targetExe = Join-Path $targetApp ([string][char]0x6BD4 + [char]0x7279 + [char]0x6D4F + [char]0x89C8 + [char]0x5668 + '.exe')
$expectedExtensionId = 'jiofmdifioeejeilfkpegipdjiopiekl'
$sourceDb = Join-Path $sourceRoaming 'db.sqlite'
$sourceExtensionManifest = Join-Path $sourceRoaming "BitExtensions\$expectedExtensionId\manifest.json"
if (-not $SkipProcessCheck) {
$running = @(Get-CimInstance Win32_Process -ErrorAction SilentlyContinue | Where-Object {
$_.Name -eq ([string][char]0x6BD4 + [char]0x7279 + [char]0x6D4F + [char]0x89C8 + [char]0x5668 + '.exe') -or
($_.ExecutablePath -and $_.ExecutablePath.StartsWith($targetApp, [System.StringComparison]::OrdinalIgnoreCase))
})
if ($running.Count -gt 0) {
throw 'BitBrowser is running. Close it and run this installer again.'
}
}
if (-not (Test-Path -LiteralPath $sourceDb -PathType Leaf)) {
throw 'The clean seed database is missing from this package.'
}
if (-not (Test-Path -LiteralPath $sourceExtensionManifest -PathType Leaf)) {
throw 'The YesCaptcha extension is missing from this package.'
}
Write-Host 'Installing BitBrowser application files...'
Copy-Tree -Source $sourceApp -Destination $targetApp
$backups = @()
$backup = Move-ToBackup -Path $targetRoaming
if ($backup) { $backups += $backup }
$backup = Move-ToBackup -Path $targetLocal
if ($backup) { $backups += $backup }
Write-Host 'Installing clean user data and preserved extensions...'
Copy-Tree -Source $sourceRoaming -Destination $targetRoaming
if (Test-Path -LiteralPath $sourceLocal -PathType Container) {
Copy-Tree -Source $sourceLocal -Destination $targetLocal
}
if (-not (Test-Path -LiteralPath $targetExe -PathType Leaf)) {
throw "Installed executable was not found: $targetExe"
}
$targetDb = Join-Path $targetRoaming 'db.sqlite'
$targetExtensionManifest = Join-Path $targetRoaming "BitExtensions\$expectedExtensionId\manifest.json"
if (-not (Test-Path -LiteralPath $targetExtensionManifest -PathType Leaf)) {
throw "YesCaptcha was not installed: $targetExtensionManifest"
}
if ((Get-FileHash -LiteralPath $sourceDb -Algorithm SHA256).Hash -ne (Get-FileHash -LiteralPath $targetDb -Algorithm SHA256).Hash) {
throw 'The clean database copy failed verification.'
}
if ((Get-FileHash -LiteralPath $sourceExtensionManifest -Algorithm SHA256).Hash -ne (Get-FileHash -LiteralPath $targetExtensionManifest -Algorithm SHA256).Hash) {
throw 'The YesCaptcha extension copy failed verification.'
}
if (-not $SkipShortcuts) {
$shell = New-Object -ComObject WScript.Shell
$desktop = [Environment]::GetFolderPath('Desktop')
$shortcutPath = Join-Path $desktop 'BitBrowser.lnk'
$shortcut = $shell.CreateShortcut($shortcutPath)
$shortcut.TargetPath = $targetExe
$shortcut.WorkingDirectory = $targetApp
$shortcut.IconLocation = $targetExe + ',0'
$shortcut.Save()
$startMenu = Join-Path $env:APPDATA 'Microsoft\Windows\Start Menu\Programs'
$startShortcutPath = Join-Path $startMenu 'BitBrowser.lnk'
$startShortcut = $shell.CreateShortcut($startShortcutPath)
$startShortcut.TargetPath = $targetExe
$startShortcut.WorkingDirectory = $targetApp
$startShortcut.IconLocation = $targetExe + ',0'
$startShortcut.Save()
}
Write-Host ''
Write-Host "Installed application: $targetApp"
Write-Host "Installed clean data: $targetRoaming"
Write-Host "Verified extension: YesCaptcha 1.4.7 ($expectedExtensionId)"
if ($backups.Count -gt 0) {
Write-Host 'Previous data was preserved at:'
foreach ($item in $backups) { Write-Host " $item" }
}
Write-Host 'No browser profiles, cookies, history, cache, proxy settings, or login token were installed.'
if (-not $NoLaunch) {
Start-Process -FilePath $targetExe -WorkingDirectory $targetApp
}