From 704d41e027021d57b26c620b2fd717a1e8d5ab95 Mon Sep 17 00:00:00 2001 From: Repinoid Date: Fri, 23 Oct 2026 13:09:07 +0300 Subject: [PATCH] Temporarily disable CSV uploads Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 4 ++-- drhider/extractor.py | 21 ++++++++++++++++++--- site/app.py | 3 +-- site/routes/api_bp.py | 11 +++++++++-- site/templates/index.html | 6 +++--- upload/backend/upload_refs/blueprint.py | 6 ++++++ 6 files changed, 39 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d8dbcd5..329ed98 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ The browser sends files one at a time: it waits for the WebDAV `PUT`, then asks - `upload/frontend/upload/put_to_vm.js` sends a raw file body with `PUT` and reports progress. - `upload/frontend/upload/upload_via_vm.js` coordinates the per-file `PUT` and `/api/upload_refs` requests. -The UI accepts `.pdf`, `.doc`, `.docx`, `.txt`, `.md`, `.csv`, and `.zip` inputs. ZIP archives are expanded by the browser picker, and their allowed inner files are uploaded individually. The backend `drhider/extractor.py` also expands ZIPs received directly (for example, through `POST /api/upload`). Per-file (50 MiB) and per-session (500 MiB) limits are enforced by the backend; the picker's entry/size/depth limits apply only while unpacking ZIP archives. +The UI accepts `.pdf`, `.doc`, `.docx`, `.txt`, `.md`, and `.zip` inputs. CSV input is temporarily disabled in the picker and rejected by both upload endpoints; CSV files inside ZIP archives are not extracted. The CSV parsing and obfuscation code remains in `drhider/extractor.py` for internal use and possible re-enabling after reliability work on the other formats. This does not affect the separate mapping CSV generated as an output for each processing session. ZIP archives are expanded by the browser picker, and their allowed inner files are uploaded individually. The backend `drhider/extractor.py` also expands ZIPs received directly (for example, through `POST /api/upload`). Per-file (50 MiB) and per-session (500 MiB) limits are enforced by the backend; the picker's entry/size/depth limits apply only while unpacking ZIP archives. ### Flask composition and routes @@ -77,7 +77,7 @@ Main endpoints: The core package is split by responsibility: -- `drhider/extractor.py` converts `.docx`, `.pdf`, and `.doc` content to text/Markdown, extracts CSV cell values for scanning, obfuscates CSV cells, and expands ZIP archives with ZIP-bomb protections. `.doc` conversion calls the configured conversion service. +- `drhider/extractor.py` converts `.docx`, `.pdf`, and `.doc` content to text/Markdown, expands ZIP archives with ZIP-bomb protections, and retains internal CSV extraction/obfuscation code. CSV input is temporarily disabled at upload entry points while reliability work focuses on other formats; the separate output mapping CSV remains enabled. `.doc` conversion calls the configured conversion service. - `drhider/scanner.py` detects entities with regular expressions and LLM-based NER, building the original-to-replacement mapping. - `drhider/replacer.py` applies that mapping to extracted text. - `drhider/builder.py` builds the obfuscated ZIP and mapping CSV. The mapping CSV is deliberately not included inside the ZIP; it is downloaded through its separate endpoint. diff --git a/drhider/extractor.py b/drhider/extractor.py index e1f9252..193d36c 100644 --- a/drhider/extractor.py +++ b/drhider/extractor.py @@ -230,7 +230,13 @@ def detect_delimiter(text: str) -> str: def csv_to_text(content: bytes) -> str: - """Распарсить CSV и склеить значения ячеек построчно для сканирования.""" + """Распарсить CSV и склеить значения ячеек построчно для сканирования. + + Входная загрузка CSV временно отключена, чтобы сосредоточить тестирование + надёжности на остальных форматах. Функция оставлена для внутренней + обработки и будущего повторного включения поддержки; не удалять её + и связанную с ней логику вместе с UI/API-ограничением загрузки. + """ text = decode_text(content).removeprefix("\ufeff") delimiter = detect_delimiter(text) reader = csv.reader( @@ -246,7 +252,13 @@ def csv_to_text(content: bytes) -> str: def obfuscate_csv(content: bytes, mapping: Dict[str, str], sorted_keys: List[str], compiled_re) -> bytes: - """Заменить сущности в CSV-ячейках, сохранив порядок строк и столбцов.""" + """Заменить сущности в CSV-ячейках, сохранив порядок строк и столбцов. + + Входная загрузка CSV временно отключена для фокусировки на надёжности + остальных форматов. Обработчик сохраняется для внутреннего использования + и будущего повторного включения; CSV-файл mapping, выдаваемый как результат, + является отдельной функцией и этой временной блокировкой не затрагивается. + """ text = decode_text(content).removeprefix("\ufeff") delimiter = detect_delimiter(text) reader = csv.reader( @@ -417,7 +429,10 @@ def expand_zips(files: List[Tuple[str, bytes, str]]) -> List[Tuple[str, bytes, s continue # Синхронизация с фронтом (listZipFiles): из zip берём ТОЛЬКО документы low = name.lower() - if not (low.endswith('.zip') or low.endswith(('.pdf', '.doc', '.docx', '.txt', '.md', '.csv'))): + # CSV-процессор сохранён, но пользовательский ввод CSV + # временно отключён. Не извлекаем CSV из ZIP, чтобы обход + # ограничения через архив не включал эту ветку обработки. + if not (low.endswith('.zip') or low.endswith(('.pdf', '.doc', '.docx', '.txt', '.md'))): continue inner_data = zf.read(info) diff --git a/site/app.py b/site/app.py index 4f17263..4a72984 100644 --- a/site/app.py +++ b/site/app.py @@ -22,7 +22,7 @@ if _sys_path_root not in sys.path: sys.path.insert(0, _sys_path_root) # Версия приложения (меняется при изменениях) -VERSION = "1.0.3" +VERSION = "1.0.4" def setup_logging(): @@ -98,4 +98,3 @@ app = create_app() if __name__ == "__main__": from waitress import serve serve(app, host="0.0.0.0", port=5000, threads=8) - diff --git a/site/routes/api_bp.py b/site/routes/api_bp.py index c8e192e..e44aca4 100644 --- a/site/routes/api_bp.py +++ b/site/routes/api_bp.py @@ -42,13 +42,20 @@ def _disconnect_exceptions(): def upload(): """Upload files to session (один или несколько).""" sid = request.form.get("session", "") - if not sid: - sid = create_session() uploaded = request.files.getlist("files") if not uploaded: log.warning("upload: no files, sid=%s", sid) return jsonify({"ok": False, "error": "No file"}), 400 + # CSV input is temporarily disabled so reliability testing can focus on the + # other document formats. Keep the CSV processing code in the core intact. + if any(safe_name(f.filename).lower().endswith(".csv") for f in uploaded): + log.warning("upload: CSV input is disabled") + return jsonify({"ok": False, "error": "CSV uploads are temporarily disabled"}), 400 + + if not sid: + sid = create_session() + added = 0 had_unnamed = False for f in uploaded: diff --git a/site/templates/index.html b/site/templates/index.html index 0d42855..ae6ba12 100644 --- a/site/templates/index.html +++ b/site/templates/index.html @@ -457,7 +457,7 @@
Обфускация документов

- Загрузите документы (.docx, .doc, .pdf, .txt, .md, .csv, .zip) — получите ZIP с обезличенными копиями.
+ Загрузите документы (.docx, .doc, .pdf, .txt, .md, .zip) — получите ZIP с обезличенными копиями.
CSV с таблицей замен скачивается отдельно.
Ограничения: один файл не более 50 МБ, суммарно не более 500 МБ. Файлы сверх лимитов помечаются статусом «пропущен» и не участвуют в обфускации. Пустые, повреждённые файлы и сканы без @@ -507,7 +507,7 @@