Files
cmsPRO/.paul/phases/04h-hotfix-https-updates/scripts/patch-packages.ps1
2026-04-26 01:44:36 +02:00

238 lines
7.6 KiB
PowerShell

<#
.SYNOPSIS
Patch wszystkich paczek aktualizacji cmsPRO: zamiana http:// -> https:// w buggy plikach.
.DESCRIPTION
Skanuje rekursywnie kazdy ZIP w updates/. Dla kazdego ZIP-a zawierajacego
pliki kandydujace z buggy URL:
1. Robi backup .bak (raz, nie nadpisuje istniejacego .bak)
2. Otwiera ZIP w trybie Update
3. Dla kazdego buggy pliku: czyta zawartosc, zamienia http -> https, zapisuje
4. Jesli istnieje sasiadujacy manifest *_manifest.json: przelicza SHA256 i aktualizuje checksum_zip
5. Loguje akcje
Output: patch-log.md (lista zmienionych paczek z SHA256 przed/po).
#>
[CmdletBinding()]
param(
[string]$UpdatesDir = "C:\visual studio code\projekty\cmsPRO\updates",
[string]$LogPath = "C:\visual studio code\projekty\cmsPRO\.paul\phases\04h-hotfix-https-updates\patch-log.md",
[switch]$DryRun
)
$ErrorActionPreference = "Stop"
Add-Type -AssemblyName System.IO.Compression.FileSystem
$BuggyPattern = 'http://www.cmspro.project-dc.pl'
$FixedPattern = 'https://www.cmspro.project-dc.pl'
$SuspectFiles = @(
'autoload/class.S.php',
'autoload/Shared/Helpers/Helpers.php',
'autoload/admin/factory/class.Update.php'
)
function Get-Sha256 {
param([string]$Path)
return (Get-FileHash -Algorithm SHA256 -Path $Path).Hash.ToLower()
}
function Patch-Zip {
param([string]$ZipPath)
$log = [PSCustomObject]@{
Package = (Resolve-Path $ZipPath).Path.Substring($UpdatesDir.Length).TrimStart('\','/')
Sha256Before = $null
Sha256After = $null
PatchedFiles = @()
ManifestUpd = $false
Skipped = $false
Error = $null
}
# backup
$bak = "$ZipPath.bak"
if (-not (Test-Path $bak)) {
Copy-Item -LiteralPath $ZipPath -Destination $bak -Force
}
$log.Sha256Before = Get-Sha256 -Path $ZipPath
# quick check: does any suspect file have buggy URL?
$needsPatch = $false
$entriesToPatch = @()
try {
$zip = [System.IO.Compression.ZipFile]::OpenRead($ZipPath)
foreach ($entry in $zip.Entries) {
$name = $entry.FullName.Replace('\','/')
if ($SuspectFiles -contains $name) {
$reader = New-Object System.IO.StreamReader($entry.Open())
$content = $reader.ReadToEnd()
$reader.Close()
if ($content.Contains($BuggyPattern)) {
$needsPatch = $true
$entriesToPatch += $name
}
}
}
$zip.Dispose()
} catch {
$log.Error = "OpenRead: $($_.Exception.Message)"
return $log
}
if (-not $needsPatch) {
$log.Skipped = $true
$log.Sha256After = $log.Sha256Before
return $log
}
if ($DryRun) {
$log.PatchedFiles = $entriesToPatch
$log.Sha256After = '(dry-run)'
return $log
}
# Patch in-place
try {
$zipUpd = [System.IO.Compression.ZipFile]::Open($ZipPath, [System.IO.Compression.ZipArchiveMode]::Update)
foreach ($name in $entriesToPatch) {
$entry = $zipUpd.Entries | Where-Object { $_.FullName.Replace('\','/') -eq $name } | Select-Object -First 1
if (-not $entry) { continue }
# Read
$stream = $entry.Open()
$reader = New-Object System.IO.StreamReader($stream)
$content = $reader.ReadToEnd()
$reader.Close()
$stream.Close()
# Replace
$newContent = $content.Replace($BuggyPattern, $FixedPattern)
if ($newContent -eq $content) { continue }
# Write back: open writable stream and truncate
$writeStream = $entry.Open()
$writeStream.SetLength(0)
$writer = New-Object System.IO.StreamWriter($writeStream, (New-Object System.Text.UTF8Encoding $false))
$writer.Write($newContent)
$writer.Flush()
$writer.Close()
$writeStream.Close()
$log.PatchedFiles += $name
}
$zipUpd.Dispose()
} catch {
$log.Error = "Patch: $($_.Exception.Message)"
return $log
}
$log.Sha256After = Get-Sha256 -Path $ZipPath
# Update manifest if exists
$verBase = [System.IO.Path]::GetFileNameWithoutExtension($ZipPath) # e.g. ver_1.519
$manifestPath = Join-Path (Split-Path $ZipPath -Parent) "${verBase}_manifest.json"
if (Test-Path $manifestPath) {
try {
$jsonRaw = [System.IO.File]::ReadAllText($manifestPath)
# Strip BOM
if ($jsonRaw.Length -gt 0 -and $jsonRaw[0] -eq [char]0xFEFF) {
$jsonRaw = $jsonRaw.Substring(1)
}
$manifest = $jsonRaw | ConvertFrom-Json
if ($manifest.PSObject.Properties.Name -contains 'checksum_zip') {
$manifest.checksum_zip = "sha256:$($log.Sha256After)"
$newJson = $manifest | ConvertTo-Json -Depth 20
$utf8 = New-Object System.Text.UTF8Encoding $false
[System.IO.File]::WriteAllText($manifestPath, $newJson, $utf8)
$log.ManifestUpd = $true
}
} catch {
$log.Error = "Manifest: $($_.Exception.Message)"
}
}
return $log
}
# --- Main ---
Write-Host "Skanuje $UpdatesDir ..." -ForegroundColor Cyan
$zips = @()
$baseInstall = Join-Path $UpdatesDir 'cmsPro.zip'
if (Test-Path $baseInstall) { $zips += $baseInstall }
$zips += Get-ChildItem -Path $UpdatesDir -Filter 'ver_*.zip' -Recurse | Sort-Object FullName | ForEach-Object { $_.FullName }
Write-Host "Paczek do sprawdzenia: $($zips.Count)" -ForegroundColor Cyan
if ($DryRun) { Write-Host "DRY-RUN: nic nie bedzie zmienione" -ForegroundColor Yellow }
$results = @()
$i = 0
foreach ($zip in $zips) {
$i++
Write-Progress -Activity "Patch paczek" -Status "$i / $($zips.Count): $(Split-Path $zip -Leaf)" -PercentComplete (($i / $zips.Count) * 100)
$results += Patch-Zip -ZipPath $zip
}
Write-Progress -Activity "Patch paczek" -Completed
$patched = $results | Where-Object { $_.PatchedFiles.Count -gt 0 -and -not $_.Error }
$skipped = $results | Where-Object { $_.Skipped }
$errored = $results | Where-Object { $_.Error }
$manifUpd = $results | Where-Object { $_.ManifestUpd }
# Log report
$lines = @()
$lines += '# Patch Log: paczki aktualizacji cmsPRO (HTTP -> HTTPS)'
$lines += ''
$lines += "**Data:** $(Get-Date -Format 'yyyy-MM-dd HH:mm')"
$lines += "**DryRun:** $DryRun"
$lines += ''
$lines += '## Podsumowanie'
$lines += ''
$lines += "| Kategoria | Liczba |"
$lines += "|-----------|--------|"
$lines += "| Paczek przeskanowanych | $($results.Count) |"
$lines += "| **Spatchowanych** | **$($patched.Count)** |"
$lines += "| Pominietych (juz OK / brak buggy) | $($skipped.Count) |"
$lines += "| Manifestow zaktualizowanych | $($manifUpd.Count) |"
$lines += "| Bledow | $($errored.Count) |"
$lines += ''
$lines += '## Spatchowane paczki'
$lines += ''
if ($patched) {
$lines += '| # | Paczka | Pliki | SHA256 (przed) | SHA256 (po) | Manifest |'
$lines += '|---|--------|-------|----------------|-------------|----------|'
$idx = 0
foreach ($r in $patched) {
$idx++
$files = ($r.PatchedFiles -join '<br>')
$man = if ($r.ManifestUpd) { 'YES' } else { '-' }
$shaBefore = if ($r.Sha256Before.Length -ge 12) { $r.Sha256Before.Substring(0,12) } else { $r.Sha256Before }
$shaAfter = if ($r.Sha256After.Length -ge 12) { $r.Sha256After.Substring(0,12) } else { $r.Sha256After }
$lines += "| $idx | ``$($r.Package)`` | $files | ``$shaBefore`` | ``$shaAfter`` | $man |"
}
} else {
$lines += '_Brak._'
}
$lines += ''
$lines += '## Bledy'
$lines += ''
if ($errored) {
foreach ($r in $errored) {
$lines += "- ``$($r.Package)`` -- $($r.Error)"
}
} else {
$lines += '_Brak._'
}
$utf8 = New-Object System.Text.UTF8Encoding $false
[System.IO.File]::WriteAllText($LogPath, ($lines -join "`r`n"), $utf8)
Write-Host ""
Write-Host "Patch zakonczony." -ForegroundColor Green
Write-Host " Spatchowanych: $($patched.Count)" -ForegroundColor Yellow
Write-Host " Manifestow updated: $($manifUpd.Count)"
Write-Host " Pominietych: $($skipped.Count)"
Write-Host " Bledow: $($errored.Count)"
Write-Host "Log: $LogPath" -ForegroundColor Cyan