From 3a948902ff87cb84c8b8a001418f5f318483d6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Mon, 29 Jun 2026 15:06:16 +0400 Subject: [PATCH] fix: clean ASCII filenames in output ZIP --- deploy/services/drhider.py | 19 +++++++++++++------ site/services/drhider.py | 19 +++++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/deploy/services/drhider.py b/deploy/services/drhider.py index ab62306..da2e760 100644 --- a/deploy/services/drhider.py +++ b/deploy/services/drhider.py @@ -17,6 +17,7 @@ import logging import tempfile import os import shutil +import datetime from typing import Dict, List, Tuple, Callable, Optional log = logging.getLogger("drhider") @@ -210,7 +211,12 @@ class TwoPassObfuscator: # --- Проход 2: замена --- results = [] + ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + seq = 0 for fname, content, ctype in files: + seq += 1 + ext = os.path.splitext(fname)[1] or ".tmp" + clean_name = f"doc_{ts}_{seq:03d}{ext}" obf_content = content if fname in all_docx: # Замена внутри docx @@ -223,7 +229,7 @@ class TwoPassObfuscator: txt = all_texts.get(fname, '') obf_content = self._replace_in_text(txt, fname) - results.append((fname, obf_content)) + results.append((clean_name, obf_content)) # Собираем ZIP + CSV csv_str = self._build_mapping_csv() @@ -253,14 +259,15 @@ class TwoPassObfuscator: for info in zf.infolist(): if info.is_dir(): continue - # cp437 → utf8 для имён + # cp437 → utf8 (как в services/unzip.py) + name = info.filename try: - inner_name = info.filename.encode('cp437').decode('utf-8') + name = name.encode("cp437").decode("utf-8", errors="replace") except (UnicodeDecodeError, UnicodeEncodeError): - inner_name = info.filename + pass # Убрать path traversal - inner_name = os.path.basename(inner_name) - if not inner_name: + name = os.path.basename(name) + if not name or name.endswith("/") or ".." in name or "/" in name or "\\" in name: continue inner_data = zf.read(info) result.append((inner_name, inner_data, "")) diff --git a/site/services/drhider.py b/site/services/drhider.py index ab62306..da2e760 100644 --- a/site/services/drhider.py +++ b/site/services/drhider.py @@ -17,6 +17,7 @@ import logging import tempfile import os import shutil +import datetime from typing import Dict, List, Tuple, Callable, Optional log = logging.getLogger("drhider") @@ -210,7 +211,12 @@ class TwoPassObfuscator: # --- Проход 2: замена --- results = [] + ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + seq = 0 for fname, content, ctype in files: + seq += 1 + ext = os.path.splitext(fname)[1] or ".tmp" + clean_name = f"doc_{ts}_{seq:03d}{ext}" obf_content = content if fname in all_docx: # Замена внутри docx @@ -223,7 +229,7 @@ class TwoPassObfuscator: txt = all_texts.get(fname, '') obf_content = self._replace_in_text(txt, fname) - results.append((fname, obf_content)) + results.append((clean_name, obf_content)) # Собираем ZIP + CSV csv_str = self._build_mapping_csv() @@ -253,14 +259,15 @@ class TwoPassObfuscator: for info in zf.infolist(): if info.is_dir(): continue - # cp437 → utf8 для имён + # cp437 → utf8 (как в services/unzip.py) + name = info.filename try: - inner_name = info.filename.encode('cp437').decode('utf-8') + name = name.encode("cp437").decode("utf-8", errors="replace") except (UnicodeDecodeError, UnicodeEncodeError): - inner_name = info.filename + pass # Убрать path traversal - inner_name = os.path.basename(inner_name) - if not inner_name: + name = os.path.basename(name) + if not name or name.endswith("/") or ".." in name or "/" in name or "\\" in name: continue inner_data = zf.read(info) result.append((inner_name, inner_data, ""))