| 1 | from pathlib import Path |
| 2 | import sys |
| 3 | import tarfile |
| 4 | import zipfile |
| 5 | |
| 6 | import pytest |
| 7 | |
| 8 | |
| 9 | PROJECT_ROOT = Path(__file__).resolve().parents[1] |
| 10 | if str(PROJECT_ROOT) not in sys.path: |
| 11 | sys.path.insert(0, str(PROJECT_ROOT)) |
| 12 | |
| 13 | |
| 14 | from api.extract_work_dir_archive import extract_archive |
| 15 | from helpers import files |
| 16 | |
| 17 | |
| 18 | def test_extract_archive_creates_unique_zip_destination(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: |
| 19 | monkeypatch.setattr(files, "_base_dir", str(tmp_path)) |
| 20 | archive = tmp_path / "notes.zip" |
| 21 | with zipfile.ZipFile(archive, "w") as bundle: |
| 22 | bundle.writestr("nested/note.txt", "hello") |
| 23 | |
| 24 | first = Path(extract_archive(str(archive))) |
| 25 | second = Path(extract_archive(str(archive))) |
| 26 | |
| 27 | assert (first / "nested" / "note.txt").read_text() == "hello" |
| 28 | assert second.name == "notes-2" |
| 29 | |
| 30 | |
| 31 | def test_extract_archive_handles_tar_gz(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: |
| 32 | monkeypatch.setattr(files, "_base_dir", str(tmp_path)) |
| 33 | source = tmp_path / "readme.txt" |
| 34 | source.write_text("hello") |
| 35 | archive = tmp_path / "bundle.tar.gz" |
| 36 | with tarfile.open(archive, "w:gz") as bundle: |
| 37 | bundle.add(source, arcname="readme.txt") |
| 38 | |
| 39 | destination = Path(extract_archive(str(archive))) |
| 40 | |
| 41 | assert (destination / "readme.txt").read_text() == "hello" |
| 42 | |
| 43 | |
| 44 | def test_extract_archive_rejects_zip_path_traversal(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: |
| 45 | monkeypatch.setattr(files, "_base_dir", str(tmp_path)) |
| 46 | archive = tmp_path / "unsafe.zip" |
| 47 | with zipfile.ZipFile(archive, "w") as bundle: |
| 48 | bundle.writestr("../escape.txt", "nope") |
| 49 | |
| 50 | with pytest.raises(ValueError, match="unsafe path"): |
| 51 | extract_archive(str(archive)) |
| 52 | |
| 53 | assert not (tmp_path / "unsafe").exists() |