<# .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 '
') $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