|
28 | 28 |
|
29 | 29 | from __future__ import annotations |
30 | 30 |
|
| 31 | +import atexit |
31 | 32 | import io |
32 | 33 | import logging |
33 | 34 | import os |
| 35 | +import tempfile |
34 | 36 | from dataclasses import dataclass |
35 | 37 | from enum import Enum |
36 | 38 | from pathlib import Path |
37 | 39 | from typing import Any |
38 | 40 |
|
| 41 | +import platformdirs |
39 | 42 | from bitcoin_qr_tools.qr_generator import QRGenerator |
40 | 43 | from bitcoin_usb.address_types import DescriptorInfo |
41 | 44 | from PIL.Image import Image as PilImage |
|
64 | 67 |
|
65 | 68 | logger = logging.getLogger(__name__) |
66 | 69 |
|
| 70 | +_TEMP_PDFS: set[Path] = set() |
| 71 | + |
| 72 | + |
| 73 | +def _cleanup_temp_pdfs() -> None: |
| 74 | + for path in list(_TEMP_PDFS): |
| 75 | + try: |
| 76 | + path.unlink() |
| 77 | + except FileNotFoundError: |
| 78 | + pass |
| 79 | + except PermissionError: |
| 80 | + logger.warning("Could not remove temporary PDF at %s", path) |
| 81 | + |
| 82 | + |
| 83 | +atexit.register(_cleanup_temp_pdfs) |
| 84 | + |
67 | 85 |
|
68 | 86 | TEXT_24_WORDS = translate("pdf", "12 or 24") |
69 | 87 | DEFAULT_MARGIN = 36 |
70 | 88 |
|
71 | 89 |
|
| 90 | +def _safe_filename_prefix(filename: str) -> str: |
| 91 | + return "".join(char if char.isalnum() or char in {"-", "_"} else "_" for char in filename) |
| 92 | + |
| 93 | + |
| 94 | +def write_and_open_temp_pdf(pdf: BasePDF, filename: str) -> None: |
| 95 | + """Write a PDF to the user cache directory and open it with the OS.""" |
| 96 | + safe_prefix = _safe_filename_prefix(filename) |
| 97 | + cache_dir = Path(platformdirs.user_cache_dir("bitcoin_safe")) |
| 98 | + cache_dir.mkdir(parents=True, exist_ok=True) |
| 99 | + temp_fd, temp_file = tempfile.mkstemp(prefix=f"{safe_prefix}-", suffix=".pdf", dir=cache_dir) |
| 100 | + os.close(temp_fd) |
| 101 | + pdf.save_pdf(temp_file) |
| 102 | + pdf.open_pdf(temp_file) |
| 103 | + _TEMP_PDFS.add(Path(temp_file)) |
| 104 | + |
| 105 | + |
72 | 106 | def pilimage_to_reportlab(pilimage: PilImage, width=200, height=200) -> Image: |
73 | 107 | """Pilimage to reportlab.""" |
74 | 108 | buffer = io.BytesIO() |
@@ -602,8 +636,5 @@ def make_and_open_pdf(wallet: Wallet, lang_code: str) -> None: |
602 | 636 | keystore_label=keystore.label, |
603 | 637 | ) |
604 | 638 | pdf_recovery.add_page_break() |
605 | | - temp_file = os.path.join( |
606 | | - Path.home(), translate("pdf", "Seed backup of {id}").format(id=wallet.id) + ".pdf" |
607 | | - ) |
608 | | - pdf_recovery.save_pdf(temp_file) |
609 | | - pdf_recovery.open_pdf(temp_file) |
| 639 | + filename = translate("pdf", "Seed backup of {id}").format(id=wallet.id) |
| 640 | + write_and_open_temp_pdf(pdf_recovery, filename) |
0 commit comments