fix: decode WinRM Cyrillic from CP866 and show deploy.log UTF-8 (0.20.17)
This commit is contained in:
@@ -19,7 +19,7 @@ _CLIXML_PROGRESS_NOISE = frozenset(
|
||||
}
|
||||
)
|
||||
_CLIXML_MARKER = "#< CLIXML"
|
||||
|
||||
_CYRILLIC_RE = re.compile(r"[\u0400-\u04FF]")
|
||||
RDP_REMOTE_STAGING = r"C:\ProgramData\RDP-login-monitor\_sac_staging"
|
||||
RDP_BUNDLE_FILES = (
|
||||
"Login_Monitor.ps1",
|
||||
@@ -128,6 +128,39 @@ def _clixml_to_plain(text: str) -> str:
|
||||
return without
|
||||
|
||||
|
||||
def _decode_text_score(text: str) -> int:
|
||||
cyrillic = len(_CYRILLIC_RE.findall(text))
|
||||
suspicious = len(re.findall(r"\?{3,}", text))
|
||||
return cyrillic * 5 - text.count("\ufffd") * 20 - suspicious * 15 - max(0, text.count("?") - cyrillic) * 2
|
||||
|
||||
|
||||
def _decode_winrm_bytes(data: bytes) -> str:
|
||||
if not data:
|
||||
return ""
|
||||
for encoding in ("utf-8-sig", "utf-8"):
|
||||
try:
|
||||
text = data.decode(encoding)
|
||||
except UnicodeDecodeError:
|
||||
break
|
||||
score = _decode_text_score(text)
|
||||
if text.isascii() or score > 0:
|
||||
return text
|
||||
best_score = -10_000
|
||||
best_text = ""
|
||||
for encoding in ("cp866", "cp1251"):
|
||||
try:
|
||||
text = data.decode(encoding)
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
score = _decode_text_score(text)
|
||||
if score > best_score:
|
||||
best_score = score
|
||||
best_text = text
|
||||
if best_text:
|
||||
return best_text
|
||||
return data.decode("utf-8", errors="replace")
|
||||
|
||||
|
||||
def _winrm_failure_detail(stdout: str, stderr: str, exit_code: int) -> str:
|
||||
stdout_plain = _clixml_to_plain(stdout)
|
||||
stderr_plain = _clixml_to_plain(stderr)
|
||||
@@ -213,8 +246,8 @@ def run_winrm_ps(
|
||||
except Exception as exc:
|
||||
return WinRmCmdResult(ok=False, message=f"WinRM error ({target}): {exc}", target=target)
|
||||
|
||||
stdout = (result.std_out or b"").decode("utf-8", errors="replace")
|
||||
stderr = (result.std_err or b"").decode("utf-8", errors="replace")
|
||||
stdout = _decode_winrm_bytes(result.std_out or b"")
|
||||
stderr = _decode_winrm_bytes(result.std_err or b"")
|
||||
exit_code = int(result.status_code)
|
||||
stdout, stderr = _sanitize_winrm_streams(stdout, stderr)
|
||||
return _finalize_winrm_run(
|
||||
@@ -260,8 +293,8 @@ def run_winrm_cmd(
|
||||
except Exception as exc:
|
||||
return WinRmCmdResult(ok=False, message=f"WinRM error ({target}): {exc}", target=target)
|
||||
|
||||
stdout = (result.std_out or b"").decode("utf-8", errors="replace")
|
||||
stderr = (result.std_err or b"").decode("utf-8", errors="replace")
|
||||
stdout = _decode_winrm_bytes(result.std_out or b"")
|
||||
stderr = _decode_winrm_bytes(result.std_err or b"")
|
||||
exit_code = int(result.status_code)
|
||||
stdout, stderr = _sanitize_winrm_streams(stdout, stderr)
|
||||
return _finalize_winrm_run(
|
||||
@@ -292,6 +325,9 @@ def _powershell_script_prelude() -> str:
|
||||
return (
|
||||
"$ProgressPreference = 'SilentlyContinue'\n"
|
||||
"$InformationPreference = 'SilentlyContinue'\n"
|
||||
"$utf8NoBom = New-Object System.Text.UTF8Encoding $false\n"
|
||||
"[Console]::OutputEncoding = $utf8NoBom\n"
|
||||
"$OutputEncoding = $utf8NoBom\n"
|
||||
)
|
||||
|
||||
|
||||
@@ -338,8 +374,14 @@ def _deploy_from_staging_body(staging_path: str) -> str:
|
||||
f"$staging = '{literal}'\n"
|
||||
"$deploy = Join-Path $staging 'Deploy-LoginMonitor.ps1'\n"
|
||||
"if (-not (Test-Path -LiteralPath $deploy)) { throw \"Deploy-LoginMonitor.ps1 missing in staging\" }\n"
|
||||
"$logPath = Join-Path $env:ProgramData 'RDP-login-monitor\\Logs\\deploy.log'\n"
|
||||
"Write-Output \"Running: $deploy -SourceShareRoot $staging\"\n"
|
||||
"powershell.exe -NoProfile -ExecutionPolicy Bypass -File $deploy -SourceShareRoot $staging\n"
|
||||
"if (Test-Path -LiteralPath $logPath) {\n"
|
||||
" Write-Output ''\n"
|
||||
" Write-Output '--- deploy.log ---'\n"
|
||||
" Get-Content -LiteralPath $logPath -Encoding UTF8 | Select-Object -Last 60\n"
|
||||
"}\n"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""Единый источник версии SAC (API, health, логи, OpenAPI)."""
|
||||
|
||||
APP_NAME = "Security Alert Center"
|
||||
APP_VERSION = "0.20.16"
|
||||
APP_VERSION = "0.20.17"
|
||||
APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}"
|
||||
|
||||
Reference in New Issue
Block a user