fix: clean ASCII filenames in output ZIP
Deploy contracts-flask / validate (push) Successful in 0s

This commit is contained in:
2026-06-29 15:06:16 +04:00
parent 97ebba64bb
commit 3a948902ff
2 changed files with 26 additions and 12 deletions
+13 -6
View File
@@ -17,6 +17,7 @@ import logging
import tempfile import tempfile
import os import os
import shutil import shutil
import datetime
from typing import Dict, List, Tuple, Callable, Optional from typing import Dict, List, Tuple, Callable, Optional
log = logging.getLogger("drhider") log = logging.getLogger("drhider")
@@ -210,7 +211,12 @@ class TwoPassObfuscator:
# --- Проход 2: замена --- # --- Проход 2: замена ---
results = [] results = []
ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
seq = 0
for fname, content, ctype in files: 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 obf_content = content
if fname in all_docx: if fname in all_docx:
# Замена внутри docx # Замена внутри docx
@@ -223,7 +229,7 @@ class TwoPassObfuscator:
txt = all_texts.get(fname, '') txt = all_texts.get(fname, '')
obf_content = self._replace_in_text(txt, fname) obf_content = self._replace_in_text(txt, fname)
results.append((fname, obf_content)) results.append((clean_name, obf_content))
# Собираем ZIP + CSV # Собираем ZIP + CSV
csv_str = self._build_mapping_csv() csv_str = self._build_mapping_csv()
@@ -253,14 +259,15 @@ class TwoPassObfuscator:
for info in zf.infolist(): for info in zf.infolist():
if info.is_dir(): if info.is_dir():
continue continue
# cp437 → utf8 для имён # cp437 → utf8 (как в services/unzip.py)
name = info.filename
try: try:
inner_name = info.filename.encode('cp437').decode('utf-8') name = name.encode("cp437").decode("utf-8", errors="replace")
except (UnicodeDecodeError, UnicodeEncodeError): except (UnicodeDecodeError, UnicodeEncodeError):
inner_name = info.filename pass
# Убрать path traversal # Убрать path traversal
inner_name = os.path.basename(inner_name) name = os.path.basename(name)
if not inner_name: if not name or name.endswith("/") or ".." in name or "/" in name or "\\" in name:
continue continue
inner_data = zf.read(info) inner_data = zf.read(info)
result.append((inner_name, inner_data, "")) result.append((inner_name, inner_data, ""))
+13 -6
View File
@@ -17,6 +17,7 @@ import logging
import tempfile import tempfile
import os import os
import shutil import shutil
import datetime
from typing import Dict, List, Tuple, Callable, Optional from typing import Dict, List, Tuple, Callable, Optional
log = logging.getLogger("drhider") log = logging.getLogger("drhider")
@@ -210,7 +211,12 @@ class TwoPassObfuscator:
# --- Проход 2: замена --- # --- Проход 2: замена ---
results = [] results = []
ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
seq = 0
for fname, content, ctype in files: 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 obf_content = content
if fname in all_docx: if fname in all_docx:
# Замена внутри docx # Замена внутри docx
@@ -223,7 +229,7 @@ class TwoPassObfuscator:
txt = all_texts.get(fname, '') txt = all_texts.get(fname, '')
obf_content = self._replace_in_text(txt, fname) obf_content = self._replace_in_text(txt, fname)
results.append((fname, obf_content)) results.append((clean_name, obf_content))
# Собираем ZIP + CSV # Собираем ZIP + CSV
csv_str = self._build_mapping_csv() csv_str = self._build_mapping_csv()
@@ -253,14 +259,15 @@ class TwoPassObfuscator:
for info in zf.infolist(): for info in zf.infolist():
if info.is_dir(): if info.is_dir():
continue continue
# cp437 → utf8 для имён # cp437 → utf8 (как в services/unzip.py)
name = info.filename
try: try:
inner_name = info.filename.encode('cp437').decode('utf-8') name = name.encode("cp437").decode("utf-8", errors="replace")
except (UnicodeDecodeError, UnicodeEncodeError): except (UnicodeDecodeError, UnicodeEncodeError):
inner_name = info.filename pass
# Убрать path traversal # Убрать path traversal
inner_name = os.path.basename(inner_name) name = os.path.basename(name)
if not inner_name: if not name or name.endswith("/") or ".." in name or "/" in name or "\\" in name:
continue continue
inner_data = zf.read(info) inner_data = zf.read(info)
result.append((inner_name, inner_data, "")) result.append((inner_name, inner_data, ""))