update
This commit is contained in:
169
.paul/phases/04h-hotfix-https-updates/scripts/audit-packages.ps1
Normal file
169
.paul/phases/04h-hotfix-https-updates/scripts/audit-packages.ps1
Normal file
@@ -0,0 +1,169 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Audit wszystkich paczek aktualizacji cmsPRO pod katem buggy http:// URL.
|
||||
|
||||
.DESCRIPTION
|
||||
Skanuje rekursywnie kazdy ZIP w updates/ (cmsPro.zip oraz updates/**/ver_*.zip).
|
||||
Dla kazdego ZIP-a sprawdza czy zawiera pliki kandydujace
|
||||
(autoload/class.S.php, autoload/Shared/Helpers/Helpers.php,
|
||||
autoload/admin/factory/class.Update.php) i czy te pliki zawieraja
|
||||
ciag 'http://www.cmspro.project-dc.pl'.
|
||||
|
||||
Output: audit-report.md (tabela markdown sortowana po wersji).
|
||||
Skrypt NIE modyfikuje paczek.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$UpdatesDir = "C:\visual studio code\projekty\cmsPRO\updates",
|
||||
[string]$ReportPath = "C:\visual studio code\projekty\cmsPRO\.paul\phases\04h-hotfix-https-updates\audit-report.md"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
|
||||
$BuggyPattern = 'http://www.cmspro.project-dc.pl'
|
||||
$SuspectFiles = @(
|
||||
'autoload/class.S.php',
|
||||
'autoload/Shared/Helpers/Helpers.php',
|
||||
'autoload/admin/factory/class.Update.php'
|
||||
)
|
||||
|
||||
function Test-ZipForBug {
|
||||
param([string]$ZipPath)
|
||||
|
||||
$result = [PSCustomObject]@{
|
||||
Package = (Resolve-Path $ZipPath).Path.Substring($UpdatesDir.Length).TrimStart('\','/')
|
||||
FilesPresent = @()
|
||||
BuggyFiles = @()
|
||||
HasBuggyUrl = $false
|
||||
Action = 'N/A'
|
||||
Error = $null
|
||||
}
|
||||
|
||||
try {
|
||||
$zip = [System.IO.Compression.ZipFile]::OpenRead($ZipPath)
|
||||
foreach ($entry in $zip.Entries) {
|
||||
$name = $entry.FullName.Replace('\','/')
|
||||
if ($SuspectFiles -contains $name) {
|
||||
$result.FilesPresent += $name
|
||||
$reader = New-Object System.IO.StreamReader($entry.Open())
|
||||
$content = $reader.ReadToEnd()
|
||||
$reader.Close()
|
||||
if ($content -match [regex]::Escape($BuggyPattern)) {
|
||||
$result.BuggyFiles += $name
|
||||
$result.HasBuggyUrl = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
$zip.Dispose()
|
||||
} catch {
|
||||
$result.Error = $_.Exception.Message
|
||||
}
|
||||
|
||||
if ($result.HasBuggyUrl) { $result.Action = 'PATCH' }
|
||||
elseif ($result.FilesPresent) { $result.Action = 'OK (already https)' }
|
||||
else { $result.Action = 'N/A (no suspect files)' }
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
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 "Znaleziono $($zips.Count) paczek." -ForegroundColor Cyan
|
||||
|
||||
$results = @()
|
||||
$i = 0
|
||||
foreach ($zip in $zips) {
|
||||
$i++
|
||||
Write-Progress -Activity "Audit paczek" -Status "$i / $($zips.Count): $(Split-Path $zip -Leaf)" -PercentComplete (($i / $zips.Count) * 100)
|
||||
$results += Test-ZipForBug -ZipPath $zip
|
||||
}
|
||||
Write-Progress -Activity "Audit paczek" -Completed
|
||||
|
||||
# --- Raport ---
|
||||
$buggy = $results | Where-Object { $_.HasBuggyUrl }
|
||||
$ok = $results | Where-Object { $_.FilesPresent -and -not $_.HasBuggyUrl }
|
||||
$none = $results | Where-Object { -not $_.FilesPresent }
|
||||
$errored = $results | Where-Object { $_.Error }
|
||||
|
||||
$lines = @()
|
||||
$lines += '# Audit Report: paczki aktualizacji cmsPRO (HTTP -> HTTPS bug)'
|
||||
$lines += ''
|
||||
$lines += "**Data:** $(Get-Date -Format 'yyyy-MM-dd HH:mm')"
|
||||
$lines += "**Katalog:** ``$UpdatesDir``"
|
||||
$lines += "**Wzorzec buggy:** ``$BuggyPattern``"
|
||||
$lines += ''
|
||||
$lines += '## Podsumowanie'
|
||||
$lines += ''
|
||||
$lines += "| Kategoria | Liczba |"
|
||||
$lines += "|-----------|--------|"
|
||||
$lines += "| Paczek przeskanowanych | $($results.Count) |"
|
||||
$lines += "| **PATCH (buggy http://)** | **$($buggy.Count)** |"
|
||||
$lines += "| OK (juz https albo brak URL) | $($ok.Count) |"
|
||||
$lines += "| N/A (brak plikow podejrzanych) | $($none.Count) |"
|
||||
$lines += "| Bledy | $($errored.Count) |"
|
||||
$lines += ''
|
||||
$lines += '## Paczki wymagajace patcha (HasBuggyUrl=true)'
|
||||
$lines += ''
|
||||
if ($buggy) {
|
||||
$lines += '| # | Paczka | Buggy pliki |'
|
||||
$lines += '|---|--------|-------------|'
|
||||
$idx = 0
|
||||
foreach ($r in $buggy) {
|
||||
$idx++
|
||||
$lines += "| $idx | ``$($r.Package)`` | $($r.BuggyFiles -join ', ') |"
|
||||
}
|
||||
} else {
|
||||
$lines += '_Brak paczek do patcha._'
|
||||
}
|
||||
$lines += ''
|
||||
$lines += '## Paczki zawierajace pliki ale juz na https (OK)'
|
||||
$lines += ''
|
||||
if ($ok) {
|
||||
$lines += '| # | Paczka | Pliki obecne |'
|
||||
$lines += '|---|--------|--------------|'
|
||||
$idx = 0
|
||||
foreach ($r in $ok) {
|
||||
$idx++
|
||||
$lines += "| $idx | ``$($r.Package)`` | $($r.FilesPresent -join ', ') |"
|
||||
}
|
||||
} else {
|
||||
$lines += '_Brak._'
|
||||
}
|
||||
$lines += ''
|
||||
$lines += '## Bledy odczytu'
|
||||
$lines += ''
|
||||
if ($errored) {
|
||||
foreach ($r in $errored) {
|
||||
$lines += "- ``$($r.Package)`` -- $($r.Error)"
|
||||
}
|
||||
} else {
|
||||
$lines += '_Brak._'
|
||||
}
|
||||
$lines += ''
|
||||
$lines += '## Pelna lista (raw)'
|
||||
$lines += ''
|
||||
$lines += '| Paczka | FilesPresent | HasBuggyUrl | Action |'
|
||||
$lines += '|--------|--------------|-------------|--------|'
|
||||
foreach ($r in $results) {
|
||||
$files = if ($r.FilesPresent) { ($r.FilesPresent -join '; ') } else { '-' }
|
||||
$lines += "| ``$($r.Package)`` | $files | $($r.HasBuggyUrl) | $($r.Action) |"
|
||||
}
|
||||
|
||||
$utf8 = New-Object System.Text.UTF8Encoding $false
|
||||
[System.IO.File]::WriteAllText($ReportPath, ($lines -join "`r`n"), $utf8)
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Audit zakonczony." -ForegroundColor Green
|
||||
Write-Host " Paczek: $($results.Count)"
|
||||
Write-Host " Do patcha: $($buggy.Count)" -ForegroundColor Yellow
|
||||
Write-Host " OK: $($ok.Count)"
|
||||
Write-Host " N/A: $($none.Count)"
|
||||
Write-Host " Bledy: $($errored.Count)"
|
||||
Write-Host "Raport: $ReportPath" -ForegroundColor Cyan
|
||||
@@ -0,0 +1,88 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Usuniecie wszystkich .bak / .preurlencode.bak / .preanchor.bak z FTP serwera i lokalnie.
|
||||
Uzywa .NET FtpWebRequest (szybsze + lepsze error handling niz curl).
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$LocalDir = "C:\visual studio code\projekty\cmsPRO\updates",
|
||||
[string]$RemoteRoot = "/public_html/updates",
|
||||
[string]$FtpHost = "host117523.hostido.net.pl",
|
||||
[string]$FtpUser = "www@cmspro.project-dc.pl",
|
||||
[string]$FtpPass = "aNDCvhA6cnHSQfM24vUE",
|
||||
[switch]$DryRun
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
$baks = Get-ChildItem $LocalDir -Recurse -File | Where-Object { $_.Name -like '*.bak' } | Sort-Object FullName
|
||||
|
||||
Write-Host "Plikow do skasowania: $($baks.Count)"
|
||||
if ($DryRun) { Write-Host "DRY-RUN" -ForegroundColor Yellow }
|
||||
|
||||
$cred = New-Object System.Net.NetworkCredential($FtpUser, $FtpPass)
|
||||
$deleted = 0
|
||||
$notFound = 0
|
||||
$failed = 0
|
||||
$failedList = @()
|
||||
$i = 0
|
||||
|
||||
function Delete-Ftp {
|
||||
param([string]$RemotePath)
|
||||
$url = "ftp://${FtpHost}${RemotePath}"
|
||||
$req = [System.Net.FtpWebRequest]::Create($url)
|
||||
$req.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
|
||||
$req.Credentials = $cred
|
||||
$req.UsePassive = $true
|
||||
$req.UseBinary = $true
|
||||
$req.KeepAlive = $false
|
||||
$req.Timeout = 30000
|
||||
try {
|
||||
$resp = $req.GetResponse()
|
||||
$resp.Close()
|
||||
return @{ ok = $true; status = 'deleted' }
|
||||
} catch [System.Net.WebException] {
|
||||
$msg = $_.Exception.Message
|
||||
if ($msg -match '550' -or $msg -match 'No such file') {
|
||||
return @{ ok = $true; status = 'not-found' }
|
||||
}
|
||||
return @{ ok = $false; status = 'error'; msg = $msg }
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($f in $baks) {
|
||||
$i++
|
||||
$rel = $f.FullName.Substring($LocalDir.Length).TrimStart('\','/').Replace('\','/')
|
||||
$remoteFull = "$RemoteRoot/$rel"
|
||||
|
||||
if (($i % 50) -eq 0) {
|
||||
Write-Host " $i / $($baks.Count) ... (deleted=$deleted notFound=$notFound failed=$failed)"
|
||||
}
|
||||
|
||||
if ($DryRun) {
|
||||
Write-Host " [DRY] DELE $remoteFull"
|
||||
continue
|
||||
}
|
||||
|
||||
$r = Delete-Ftp -RemotePath $remoteFull
|
||||
if ($r.ok) {
|
||||
if ($r.status -eq 'deleted') { $deleted++ } else { $notFound++ }
|
||||
Remove-Item -LiteralPath $f.FullName -Force
|
||||
} else {
|
||||
$failed++
|
||||
$failedList += "$rel -- $($r.msg)"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Zakonczono." -ForegroundColor Green
|
||||
Write-Host " Usuniete (FTP+lokal): $deleted"
|
||||
Write-Host " Brak na serwerze (lokal usuniete): $notFound"
|
||||
Write-Host " Bledy: $failed"
|
||||
if ($failedList) {
|
||||
Write-Host "Pierwsze 10 bledow:"
|
||||
$failedList | Select-Object -First 10 | ForEach-Object { Write-Host " $_" }
|
||||
$logPath = "C:\visual studio code\projekty\cmsPRO\.paul\phases\04h-hotfix-https-updates\cleanup-errors.log"
|
||||
$failedList | Out-File -FilePath $logPath -Encoding utf8
|
||||
Write-Host "Pelny log bledow: $logPath"
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Wstrzykuje "kotwice fixa" do ver_1.519.zip.
|
||||
|
||||
.DESCRIPTION
|
||||
ver_1.519.zip oryginalnie zawiera tylko class.Articles.php.
|
||||
Dodaje do niego:
|
||||
- autoload/class.S.php z ver_1.518.zip (juz patched, https://)
|
||||
- autoload/admin/factory/class.Update.php z ver_1.517.zip (juz patched, https://)
|
||||
|
||||
Cel: kazda nowa instalacja cmsPRO przechodzaca update do 1.519 dostaje
|
||||
klient HTTPS dla mechanizmu wykrywania nowych wersji.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$UpdatesDir = "C:\visual studio code\projekty\cmsPRO\updates"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
|
||||
$Target = Join-Path $UpdatesDir '1.50\ver_1.519.zip'
|
||||
$SrcS = Join-Path $UpdatesDir '1.50\ver_1.518.zip'
|
||||
$SrcUpd = Join-Path $UpdatesDir '1.50\ver_1.517.zip'
|
||||
|
||||
# Backup target (oddzielny od standardowego .bak po patch-packages.ps1)
|
||||
$bak = "$Target.preanchor.bak"
|
||||
if (-not (Test-Path $bak)) {
|
||||
Copy-Item -LiteralPath $Target -Destination $bak -Force
|
||||
Write-Host "Backup utworzony: $bak" -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
function Read-EntryBytes {
|
||||
param([string]$ZipPath, [string]$EntryName)
|
||||
$zip = [System.IO.Compression.ZipFile]::OpenRead($ZipPath)
|
||||
try {
|
||||
$entry = $zip.Entries | Where-Object { $_.FullName.Replace('\','/') -eq $EntryName } | Select-Object -First 1
|
||||
if (-not $entry) { throw "Entry not found: $EntryName in $ZipPath" }
|
||||
$stream = $entry.Open()
|
||||
$ms = New-Object System.IO.MemoryStream
|
||||
$stream.CopyTo($ms)
|
||||
$stream.Close()
|
||||
return $ms.ToArray()
|
||||
} finally {
|
||||
$zip.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
function Add-EntryFromBytes {
|
||||
param([string]$ZipPath, [string]$EntryName, [byte[]]$Content)
|
||||
$zip = [System.IO.Compression.ZipFile]::Open($ZipPath, [System.IO.Compression.ZipArchiveMode]::Update)
|
||||
try {
|
||||
# remove existing if present
|
||||
$existing = $zip.Entries | Where-Object { $_.FullName.Replace('\','/') -eq $EntryName } | Select-Object -First 1
|
||||
if ($existing) { $existing.Delete() }
|
||||
$newEntry = $zip.CreateEntry($EntryName, [System.IO.Compression.CompressionLevel]::Optimal)
|
||||
$stream = $newEntry.Open()
|
||||
$stream.Write($Content, 0, $Content.Length)
|
||||
$stream.Close()
|
||||
} finally {
|
||||
$zip.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
# 1. Read source files
|
||||
Write-Host "Czytam autoload/class.S.php z ver_1.518.zip..." -ForegroundColor Cyan
|
||||
$bytesS = Read-EntryBytes -ZipPath $SrcS -EntryName 'autoload/class.S.php'
|
||||
Write-Host " -> $($bytesS.Length) bytes"
|
||||
|
||||
Write-Host "Czytam autoload/admin/factory/class.Update.php z ver_1.517.zip..." -ForegroundColor Cyan
|
||||
$bytesUpd = Read-EntryBytes -ZipPath $SrcUpd -EntryName 'autoload/admin/factory/class.Update.php'
|
||||
Write-Host " -> $($bytesUpd.Length) bytes"
|
||||
|
||||
# 2. Verify they contain https:// (sanity check)
|
||||
$strS = [System.Text.Encoding]::UTF8.GetString($bytesS)
|
||||
$strUpd = [System.Text.Encoding]::UTF8.GetString($bytesUpd)
|
||||
if ($strS -match 'http://www\.cmspro\.project-dc\.pl' -or $strS -notmatch 'https://www\.cmspro\.project-dc\.pl') {
|
||||
throw "class.S.php z ver_1.518.zip nie jest patched (nadal ma http:// lub brak URL)"
|
||||
}
|
||||
if ($strUpd -match 'http://www\.cmspro\.project-dc\.pl' -or $strUpd -notmatch 'https://www\.cmspro\.project-dc\.pl') {
|
||||
throw "class.Update.php z ver_1.517.zip nie jest patched"
|
||||
}
|
||||
Write-Host "Sanity check OK: oba pliki maja https://" -ForegroundColor Green
|
||||
|
||||
# 3. Inject into ver_1.519.zip
|
||||
Write-Host "Wstrzykuje do ver_1.519.zip..." -ForegroundColor Cyan
|
||||
Add-EntryFromBytes -ZipPath $Target -EntryName 'autoload/class.S.php' -Content $bytesS
|
||||
Add-EntryFromBytes -ZipPath $Target -EntryName 'autoload/admin/factory/class.Update.php' -Content $bytesUpd
|
||||
|
||||
# 4. Verify
|
||||
Write-Host "Weryfikacja..." -ForegroundColor Cyan
|
||||
$zip = [System.IO.Compression.ZipFile]::OpenRead($Target)
|
||||
$entries = $zip.Entries | ForEach-Object { $_.FullName.Replace('\','/') }
|
||||
$zip.Dispose()
|
||||
|
||||
$ok = $true
|
||||
foreach ($req in @('autoload/class.S.php', 'autoload/admin/factory/class.Update.php', 'autoload/admin/controls/class.Articles.php')) {
|
||||
if ($entries -contains $req) {
|
||||
Write-Host " [OK] $req"
|
||||
} else {
|
||||
Write-Host " [MISSING] $req" -ForegroundColor Red
|
||||
$ok = $false
|
||||
}
|
||||
}
|
||||
|
||||
# Re-check no http://
|
||||
$rezip = [System.IO.Compression.ZipFile]::OpenRead($Target)
|
||||
foreach ($e in $rezip.Entries) {
|
||||
$n = $e.FullName.Replace('\','/')
|
||||
if ($n -in @('autoload/class.S.php', 'autoload/admin/factory/class.Update.php')) {
|
||||
$r = New-Object System.IO.StreamReader($e.Open())
|
||||
$c = $r.ReadToEnd(); $r.Close()
|
||||
if ($c -match 'http://www\.cmspro\.project-dc\.pl') {
|
||||
Write-Host " [BUGGY] $n nadal ma http://" -ForegroundColor Red
|
||||
$ok = $false
|
||||
} else {
|
||||
Write-Host " [HTTPS] $n czyste" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
}
|
||||
$rezip.Dispose()
|
||||
|
||||
if ($ok) {
|
||||
$sha = (Get-FileHash -Algorithm SHA256 -Path $Target).Hash.ToLower()
|
||||
Write-Host ""
|
||||
Write-Host "ver_1.519.zip jest teraz kotwica fixa." -ForegroundColor Green
|
||||
Write-Host " SHA256: $sha"
|
||||
} else {
|
||||
Write-Host "Wystapily problemy - sprawdz reczny." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
237
.paul/phases/04h-hotfix-https-updates/scripts/patch-packages.ps1
Normal file
237
.paul/phases/04h-hotfix-https-updates/scripts/patch-packages.ps1
Normal file
@@ -0,0 +1,237 @@
|
||||
<#
|
||||
.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
|
||||
@@ -0,0 +1,227 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Patch wszystkich paczek aktualizacji: dodanie urlencode() na update_key w URL.
|
||||
|
||||
.DESCRIPTION
|
||||
Po wczesniejszym patchu http->https, klucz licencji nadal wysylany jako raw string.
|
||||
Klucze zawierajace # @ : $ etc. lamia URL. Fix: urlencode($settings['update_key']).
|
||||
|
||||
Wzorce zamiany (oba warianty pliku class.S.php legacy oraz Helpers.php nowy):
|
||||
1. ?key=' . $settings['update_key']) -> ?key=' . urlencode($settings['update_key']))
|
||||
2. ?key=' . $settings['update_key'] ) -> ?key=' . urlencode( $settings['update_key'] ) )
|
||||
|
||||
Idempotentny: pomija pliki ktore juz maja urlencode().
|
||||
#>
|
||||
|
||||
[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-urlencode-log.md"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
|
||||
$SuspectFiles = @(
|
||||
'autoload/class.S.php',
|
||||
'autoload/Shared/Helpers/Helpers.php',
|
||||
'autoload/admin/factory/class.Update.php'
|
||||
)
|
||||
|
||||
# Zwraca $true jesli content zawiera buggy pattern (raw $settings['update_key'] w URL)
|
||||
function Test-NeedsUrlencode {
|
||||
param([string]$Content)
|
||||
# already has urlencode wrapping update_key?
|
||||
if ($Content -match "urlencode\s*\(\s*\`$settings\[\s*'update_key'\s*\]\s*\)") {
|
||||
# check if there's still any RAW occurrence
|
||||
# Strategy: count raw vs encoded occurrences
|
||||
$raw = ([regex]::Matches($Content, "\`$settings\[\s*'update_key'\s*\]")).Count
|
||||
$enc = ([regex]::Matches($Content, "urlencode\s*\(\s*\`$settings\[\s*'update_key'\s*\]\s*\)")).Count
|
||||
return ($raw -gt $enc) # any raw not yet wrapped
|
||||
}
|
||||
return ($Content -match "key=['""]?\s*\.\s*\`$settings\[\s*'update_key'\s*\]")
|
||||
}
|
||||
|
||||
function Apply-UrlencodePatch {
|
||||
param([string]$Content)
|
||||
# Two flavors of whitespace: with and without spaces inside brackets
|
||||
# Replacement strategy: find $settings['update_key'] preceded by something containing ?key= and . and replace with urlencode wrap
|
||||
# Safest: match the full "?key=' . $settings['update_key']" with optional spaces/quotes/closing ).
|
||||
|
||||
# Variant A: ?key=' . $settings['update_key'] (no trailing space, may have ) or ; after)
|
||||
$newContent = [regex]::Replace($Content,
|
||||
"(\?key=['""]?\s*\.\s*)(\`$settings\[\s*'update_key'\s*\])",
|
||||
'$1urlencode($2)'
|
||||
)
|
||||
return $newContent
|
||||
}
|
||||
|
||||
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 (separate from previous .bak)
|
||||
$bak = "$ZipPath.preurlencode.bak"
|
||||
if (-not (Test-Path $bak)) {
|
||||
Copy-Item -LiteralPath $ZipPath -Destination $bak -Force
|
||||
}
|
||||
$log.Sha256Before = (Get-FileHash -Algorithm SHA256 -Path $ZipPath).Hash.ToLower()
|
||||
|
||||
# Find entries needing patch
|
||||
$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 (Test-NeedsUrlencode -Content $content) {
|
||||
$entriesToPatch += $name
|
||||
}
|
||||
}
|
||||
}
|
||||
$zip.Dispose()
|
||||
} catch {
|
||||
$log.Error = "OpenRead: $($_.Exception.Message)"
|
||||
return $log
|
||||
}
|
||||
|
||||
if (-not $entriesToPatch) {
|
||||
$log.Skipped = $true
|
||||
$log.Sha256After = $log.Sha256Before
|
||||
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 }
|
||||
|
||||
$stream = $entry.Open()
|
||||
$reader = New-Object System.IO.StreamReader($stream)
|
||||
$content = $reader.ReadToEnd()
|
||||
$reader.Close()
|
||||
$stream.Close()
|
||||
|
||||
$newContent = Apply-UrlencodePatch -Content $content
|
||||
if ($newContent -eq $content) { continue }
|
||||
|
||||
$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-FileHash -Algorithm SHA256 -Path $ZipPath).Hash.ToLower()
|
||||
|
||||
# Update manifest
|
||||
$verBase = [System.IO.Path]::GetFileNameWithoutExtension($ZipPath)
|
||||
$manifestPath = Join-Path (Split-Path $ZipPath -Parent) "${verBase}_manifest.json"
|
||||
if (Test-Path $manifestPath) {
|
||||
try {
|
||||
$jsonRaw = [System.IO.File]::ReadAllText($manifestPath)
|
||||
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
|
||||
|
||||
$results = @()
|
||||
$i = 0
|
||||
foreach ($zip in $zips) {
|
||||
$i++
|
||||
Write-Progress -Activity "Patch urlencode" -Status "$i / $($zips.Count)" -PercentComplete (($i / $zips.Count) * 100)
|
||||
$results += Patch-Zip -ZipPath $zip
|
||||
}
|
||||
Write-Progress -Activity "Patch urlencode" -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
|
||||
$lines = @()
|
||||
$lines += '# Patch Log: urlencode($settings[update_key])'
|
||||
$lines += ''
|
||||
$lines += "**Data:** $(Get-Date -Format 'yyyy-MM-dd HH:mm')"
|
||||
$lines += ''
|
||||
$lines += "Spatchowanych: $($patched.Count)"
|
||||
$lines += "Pominietych: $($skipped.Count)"
|
||||
$lines += "Manifestow zaktualizowanych: $($manifUpd.Count)"
|
||||
$lines += "Bledow: $($errored.Count)"
|
||||
$lines += ''
|
||||
$lines += '## Spatchowane'
|
||||
if ($patched) {
|
||||
$lines += '| # | Paczka | Pliki | SHA256 (po) |'
|
||||
$lines += '|---|--------|-------|-------------|'
|
||||
$idx = 0
|
||||
foreach ($r in $patched) {
|
||||
$idx++
|
||||
$files = ($r.PatchedFiles -join '<br>')
|
||||
$sha = if ($r.Sha256After.Length -ge 16) { $r.Sha256After.Substring(0,16) } else { $r.Sha256After }
|
||||
$lines += "| $idx | ``$($r.Package)`` | $files | ``$sha`` |"
|
||||
}
|
||||
}
|
||||
$lines += ''
|
||||
if ($errored) {
|
||||
$lines += '## Bledy'
|
||||
foreach ($r in $errored) { $lines += "- ``$($r.Package)`` -- $($r.Error)" }
|
||||
}
|
||||
|
||||
$utf8 = New-Object System.Text.UTF8Encoding $false
|
||||
[System.IO.File]::WriteAllText($LogPath, ($lines -join "`r`n"), $utf8)
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Patch urlencode 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
|
||||
Reference in New Issue
Block a user