From b9287a0ebb40d9a88ebaf8d01ec59f861591b9b0 Mon Sep 17 00:00:00 2001 From: Alex Pyrgiotis Date: Wed, 8 Feb 2023 22:10:57 +0200 Subject: [PATCH] Allow specifying config/cache directories Allow specifying the config/cache directories that Dangerzone will use, both for the CLI and the GUI, via CLI arguments. This way, the user has better control of where Dangerzone will save its state and, most importantly, we can use this feature to make each test run in a different directory. Moreover, we fix an issue where the temporary conversion artifacts were stored in the configuration directory, instead of the cache directory. Note that while most OSes (Windows and Linux) offer a way to specify these directories through environment variables, the same does not apply to MacOS [1], so having a CLI flag is required. [1]: https://github.com/platformdirs/platformdirs/issues/4 --- dangerzone/cli.py | 20 +++++++++++--- dangerzone/gui/__init__.py | 31 ++++++++++++++++++---- dangerzone/gui/logic.py | 7 +++-- dangerzone/isolation_provider/container.py | 8 +++--- dangerzone/logic.py | 7 ++--- dangerzone/util.py | 10 +++++++ 6 files changed, 65 insertions(+), 18 deletions(-) diff --git a/dangerzone/cli.py b/dangerzone/cli.py index d96c7a806..555f1475c 100644 --- a/dangerzone/cli.py +++ b/dangerzone/cli.py @@ -5,7 +5,7 @@ import click from colorama import Back, Fore, Style -from . import args, errors +from . import args, errors, util from .document import ARCHIVE_SUBDIR, SAFE_EXTENSION from .isolation_provider.container import Container from .isolation_provider.dummy import Dummy @@ -33,6 +33,18 @@ def print_header(s: str) -> None: flag_value=True, help=f"Archives the unsafe version in a subdirectory named '{ARCHIVE_SUBDIR}'", ) +@click.option( + "--config-dir", + default=util.get_default_config_dir(), + show_default=True, + help="The user directory where Dangerzone will store configuration files", +) +@click.option( + "--cache-dir", + default=util.get_default_cache_dir(), + show_default=True, + help="The user directory where Dangerzone will store temporary files", +) @click.option( "--unsafe-dummy-conversion", "dummy_conversion", flag_value=True, hidden=True ) @@ -50,14 +62,16 @@ def cli_main( ocr_lang: Optional[str], filenames: List[str], archive: bool, + config_dir: str, + cache_dir: str, dummy_conversion: bool, ) -> None: setup_logging() if getattr(sys, "dangerzone_dev", False) and dummy_conversion: - dangerzone = DangerzoneCore(Dummy()) + dangerzone = DangerzoneCore(Dummy(), config_dir) else: - dangerzone = DangerzoneCore(Container()) + dangerzone = DangerzoneCore(Container(cache_dir), config_dir) display_banner() if len(filenames) == 1 and output_filename: diff --git a/dangerzone/gui/__init__.py b/dangerzone/gui/__init__.py index ce8c3a88f..2775ee66c 100644 --- a/dangerzone/gui/__init__.py +++ b/dangerzone/gui/__init__.py @@ -20,7 +20,7 @@ except ImportError: from PySide2 import QtCore, QtGui, QtWidgets -from .. import args, errors +from .. import args, errors, util from ..document import Document from ..isolation_provider.container import Container from ..isolation_provider.dummy import Dummy @@ -59,6 +59,18 @@ def monkeypatch_event(arg__1: QtCore.QEvent) -> bool: @click.command() +@click.option( + "--config-dir", + default=util.get_default_config_dir(), + show_default=True, + help="The user directory where Dangerzone will store configuration files", +) +@click.option( + "--cache-dir", + default=util.get_default_cache_dir(), + show_default=True, + help="The user directory where Dangerzone will store temporary files", +) @click.option( "--unsafe-dummy-conversion", "dummy_conversion", flag_value=True, hidden=True ) @@ -71,7 +83,12 @@ def monkeypatch_event(arg__1: QtCore.QEvent) -> bool: ) @click.version_option(version=get_version(), message="%(version)s") @errors.handle_document_errors -def gui_main(dummy_conversion: bool, filenames: Optional[List[str]]) -> bool: +def gui_main( + dummy_conversion: bool, + config_dir: str, + cache_dir: str, + filenames: Optional[List[str]], +) -> bool: setup_logging() if platform.system() == "Darwin": @@ -91,10 +108,14 @@ def gui_main(dummy_conversion: bool, filenames: Optional[List[str]]) -> bool: # Common objects if getattr(sys, "dangerzone_dev", False) and dummy_conversion: dummy = Dummy() - dangerzone = DangerzoneGui(app, isolation_provider=dummy) + dangerzone = DangerzoneGui( + app, isolation_provider=dummy, appdata_path=config_dir + ) else: - container = Container() - dangerzone = DangerzoneGui(app, isolation_provider=container) + container = Container(cache_dir) + dangerzone = DangerzoneGui( + app, isolation_provider=container, appdata_path=config_dir + ) # Allow Ctrl-C to smoothly quit the program instead of throwing an exception signal.signal(signal.SIGINT, signal.SIG_DFL) diff --git a/dangerzone/gui/logic.py b/dangerzone/gui/logic.py index 021cf2c1b..8e4cb47d2 100644 --- a/dangerzone/gui/logic.py +++ b/dangerzone/gui/logic.py @@ -36,9 +36,12 @@ class DangerzoneGui(DangerzoneCore): """ def __init__( - self, app: QtWidgets.QApplication, isolation_provider: IsolationProvider + self, + app: QtWidgets.QApplication, + isolation_provider: IsolationProvider, + appdata_path: str, ) -> None: - super().__init__(isolation_provider) + super().__init__(isolation_provider, appdata_path) # Qt app self.app = app diff --git a/dangerzone/isolation_provider/container.py b/dangerzone/isolation_provider/container.py index 212debd87..a4fe05fa9 100644 --- a/dangerzone/isolation_provider/container.py +++ b/dangerzone/isolation_provider/container.py @@ -9,8 +9,6 @@ import tempfile from typing import Callable, List, Optional, Tuple -import appdirs - from ..document import Document from ..util import get_resource_path, get_subprocess_startupinfo from .base import IsolationProvider @@ -36,8 +34,8 @@ class Container(IsolationProvider): # Name of the dangerzone container CONTAINER_NAME = "dangerzone.rocks/dangerzone" - def __init__(self) -> None: - pass + def __init__(self, cache_dir: str) -> None: + self.cache_dir = cache_dir @staticmethod def get_runtime_name() -> str: @@ -227,7 +225,7 @@ def _convert( else: ocr = "0" - dz_tmp = os.path.join(appdirs.user_config_dir("dangerzone"), "tmp") + dz_tmp = os.path.join(self.cache_dir, "tmp") os.makedirs(dz_tmp, exist_ok=True) tmpdir = tempfile.TemporaryDirectory(dir=dz_tmp) diff --git a/dangerzone/logic.py b/dangerzone/logic.py index db6b1e172..57a1edc82 100644 --- a/dangerzone/logic.py +++ b/dangerzone/logic.py @@ -9,7 +9,6 @@ import sys from typing import Callable, List, Optional -import appdirs import colorama from . import errors @@ -26,12 +25,14 @@ class DangerzoneCore(object): Singleton of shared state / functionality throughout the app """ - def __init__(self, isolation_provider: IsolationProvider) -> None: + def __init__( + self, isolation_provider: IsolationProvider, appdata_path: str + ) -> None: # Initialize terminal colors colorama.init(autoreset=True) # App data folder - self.appdata_path = appdirs.user_config_dir("dangerzone") + self.appdata_path = appdata_path # Languages supported by tesseract with open(get_resource_path("ocr-languages.json"), "r") as f: diff --git a/dangerzone/util.py b/dangerzone/util.py index 67fdaf010..9a7f758ec 100644 --- a/dangerzone/util.py +++ b/dangerzone/util.py @@ -3,6 +3,16 @@ import subprocess import sys +import appdirs + + +def get_default_config_dir() -> str: + return appdirs.user_config_dir("dangerzone") + + +def get_default_cache_dir() -> str: + return appdirs.user_cache_dir("dangerzone") + def get_resource_path(filename: str) -> str: if getattr(sys, "dangerzone_dev", False):