diff --git a/dangerzone/cli.py b/dangerzone/cli.py index 29cae8d..8e07a41 100644 --- a/dangerzone/cli.py +++ b/dangerzone/cli.py @@ -7,6 +7,7 @@ from typing import Optional import click from colorama import Back, Fore, Style +from . import container from .common import Common from .container import convert from .global_common import GlobalCommon @@ -91,7 +92,7 @@ def cli_main( exit(1) # Ensure container is installed - global_common.install_container() + container.install_container() # Convert the document print_header("Converting document to safe PDF") diff --git a/dangerzone/container.py b/dangerzone/container.py index 405d947..4caa4dc 100644 --- a/dangerzone/container.py +++ b/dangerzone/container.py @@ -1,3 +1,4 @@ +import gzip import logging import os import pipes @@ -9,7 +10,9 @@ from typing import Callable, List, Optional import appdirs -from .util import get_resource_path +from .util import get_resource_path, get_subprocess_startupinfo + +container_name = "dangerzone.rocks/dangerzone" # What container tech is used for this platform? if platform.system() == "Linux": @@ -31,6 +34,95 @@ log = logging.getLogger(__name__) container_name = "dangerzone.rocks/dangerzone" +def get_container_runtime() -> str: + if platform.system() == "Linux": + runtime_name = "podman" + else: + runtime_name = "docker" + runtime = shutil.which(runtime_name) + if runtime is None: + raise Exception(f"{runtime_name} is not installed") + return runtime + + +def install_container() -> Optional[bool]: + """ + Make sure the podman container is installed. Linux only. + """ + if is_container_installed(): + return True + + # Load the container into podman + log.info("Installing Dangerzone container image...") + + p = subprocess.Popen( + [get_container_runtime(), "load"], + stdin=subprocess.PIPE, + startupinfo=get_subprocess_startupinfo(), + ) + + chunk_size = 10240 + compressed_container_path = get_resource_path("container.tar.gz") + with gzip.open(compressed_container_path) as f: + while True: + chunk = f.read(chunk_size) + if len(chunk) > 0: + if p.stdin: + p.stdin.write(chunk) + else: + break + p.communicate() + + if not is_container_installed(): + log.error("Failed to install the container image") + return False + + log.info("Container image installed") + return True + + +def is_container_installed() -> bool: + """ + See if the podman container is installed. Linux only. + """ + # Get the image id + with open(get_resource_path("image-id.txt")) as f: + expected_image_id = f.read().strip() + + # See if this image is already installed + installed = False + found_image_id = subprocess.check_output( + [ + get_container_runtime(), + "image", + "list", + "--format", + "{{.ID}}", + container_name, + ], + text=True, + startupinfo=get_subprocess_startupinfo(), + ) + found_image_id = found_image_id.strip() + + if found_image_id == expected_image_id: + installed = True + elif found_image_id == "": + pass + else: + log.info("Deleting old dangerzone container image") + + try: + subprocess.check_output( + [get_container_runtime(), "rmi", "--force", found_image_id], + startupinfo=get_subprocess_startupinfo(), + ) + except: + log.warning("Couldn't delete old container image, so leaving it there") + + return installed + + def exec(args: List[str], stdout_callback: Callable[[str], None] = None) -> int: args_str = " ".join(pipes.quote(s) for s in args) log.info("> " + args_str) diff --git a/dangerzone/global_common.py b/dangerzone/global_common.py index d5619fd..e7928d2 100644 --- a/dangerzone/global_common.py +++ b/dangerzone/global_common.py @@ -13,7 +13,7 @@ import colorama from .container import convert from .settings import Settings -from .util import get_resource_path, get_subprocess_startupinfo +from .util import get_resource_path log = logging.getLogger(__name__) @@ -30,98 +30,9 @@ class GlobalCommon(object): # App data folder self.appdata_path = appdirs.user_config_dir("dangerzone") - # Container - self.container_name = "dangerzone.rocks/dangerzone" - # Languages supported by tesseract with open(get_resource_path("ocr-languages.json"), "r") as f: self.ocr_languages = json.load(f) # Load settings self.settings = Settings(self) - - def get_container_runtime(self) -> str: - if platform.system() == "Linux": - runtime_name = "podman" - else: - runtime_name = "docker" - runtime = shutil.which(runtime_name) - if runtime is None: - raise Exception(f"{runtime_name} is not installed") - return runtime - - def install_container(self) -> Optional[bool]: - """ - Make sure the podman container is installed. Linux only. - """ - if self.is_container_installed(): - return True - - # Load the container into podman - log.info("Installing Dangerzone container image...") - - p = subprocess.Popen( - [self.get_container_runtime(), "load"], - stdin=subprocess.PIPE, - startupinfo=get_subprocess_startupinfo(), - ) - - chunk_size = 10240 - compressed_container_path = get_resource_path("container.tar.gz") - with gzip.open(compressed_container_path) as f: - while True: - chunk = f.read(chunk_size) - if len(chunk) > 0: - if p.stdin: - p.stdin.write(chunk) - else: - break - p.communicate() - - if not self.is_container_installed(): - log.error("Failed to install the container image") - return False - - log.info("Container image installed") - return True - - def is_container_installed(self) -> bool: - """ - See if the podman container is installed. Linux only. - """ - # Get the image id - with open(get_resource_path("image-id.txt")) as f: - expected_image_id = f.read().strip() - - # See if this image is already installed - installed = False - found_image_id = subprocess.check_output( - [ - self.get_container_runtime(), - "image", - "list", - "--format", - "{{.ID}}", - self.container_name, - ], - text=True, - startupinfo=get_subprocess_startupinfo(), - ) - found_image_id = found_image_id.strip() - - if found_image_id == expected_image_id: - installed = True - elif found_image_id == "": - pass - else: - log.info("Deleting old dangerzone container image") - - try: - subprocess.check_output( - [self.get_container_runtime(), "rmi", "--force", found_image_id], - startupinfo=get_subprocess_startupinfo(), - ) - except: - log.warning("Couldn't delete old container image, so leaving it there") - - return installed diff --git a/dangerzone/gui/main_window.py b/dangerzone/gui/main_window.py index 1f9a178..00dfd48 100644 --- a/dangerzone/gui/main_window.py +++ b/dangerzone/gui/main_window.py @@ -10,6 +10,7 @@ from typing import Optional from colorama import Fore, Style from PySide2 import QtCore, QtGui, QtWidgets +from .. import container from ..common import Common from ..container import convert from ..global_common import GlobalCommon @@ -103,7 +104,7 @@ class InstallContainerThread(QtCore.QThread): self.global_common = global_common def run(self) -> None: - self.global_common.install_container() + container.install_container() self.finished.emit()