From ae7c919d8ed4bf556de8e248e9c6a61af2ac1b32 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Feb 2020 15:07:49 -0800 Subject: [PATCH 1/3] Use docker for ubuntu and debian, and provide GUI for adding user to docker group --- BUILD.md | 4 +- dangerzone/__init__.py | 6 +++ dangerzone/common.py | 98 +++++++++++++++++++++++++++++++++++++++++- stdeb.cfg | 2 +- 4 files changed, 104 insertions(+), 6 deletions(-) diff --git a/BUILD.md b/BUILD.md index cef74da..0c30e80 100644 --- a/BUILD.md +++ b/BUILD.md @@ -9,12 +9,10 @@ git submodule update ## Debian/Ubuntu -You need [podman](https://podman.io/getting-started/installation) ([these instructions](https://kushaldas.in/posts/podman-on-debian-buster.html) are useful for installing in Debian or Ubuntu). - Install dependencies: ```sh -sudo apt install -y python3 python3-pyqt5 python3-appdirs python3-click python3-xdg +sudo apt install -y docker.io python3 python3-pyqt5 python3-appdirs python3-click python3-xdg ``` Run from source tree: diff --git a/dangerzone/__init__.py b/dangerzone/__init__.py index 4b9e3de..06bcb36 100644 --- a/dangerzone/__init__.py +++ b/dangerzone/__init__.py @@ -48,6 +48,12 @@ def main(filename): # Common object common = Common(app) + # If we're using Linux and docker, see if we need to add the user to the docker group + if platform.system() == "Linux" and common.container_runtime == "/usr/bin/docker": + if not common.ensure_user_is_in_docker_group(): + print("Failed to add user to docker group") + return + # See if we need to install Docker... if platform.system() == "Darwin" and ( not is_docker_installed(common) or not is_docker_ready(common) diff --git a/dangerzone/common.py b/dangerzone/common.py index 718956a..2da0ebe 100644 --- a/dangerzone/common.py +++ b/dangerzone/common.py @@ -6,7 +6,7 @@ import appdirs import platform import subprocess import shlex -from PyQt5 import QtGui +from PyQt5 import QtCore, QtGui, QtWidgets if platform.system() == "Darwin": import CoreServices @@ -14,6 +14,8 @@ if platform.system() == "Darwin": import plistlib elif platform.system() == "Linux": + import grp + import getpass from xdg.DesktopEntry import DesktopEntry from .settings import Settings @@ -62,7 +64,14 @@ class Common(object): "C:\\Program Files\\Docker\\Docker\\resources\\bin\\docker.exe" ) else: - self.container_runtime = "podman" + # Linux + + # If this is fedora-like, use podman + if os.path.exists("/usr/bin/dnf"): + self.container_runtime = "podman" + # Otherwise, use docker + else: + self.container_runtime = "/usr/bin/docker" # Preload list of PDF viewers on computer self.pdf_viewers = self._find_pdf_viewers() @@ -351,6 +360,39 @@ class Common(object): return pdf_viewers + def ensure_user_is_in_docker_group(self): + try: + groupinfo = grp.getgrnam("docker") + except: + # Ignore if group is not found + return True + + username = getpass.getuser() + if username not in groupinfo.gr_mem: + # User is not in docker group, so prompt about adding the user to the docker group + message = "Dangerzone requires Docker.

Click Ok to add your user to the 'docker' group. You will have to type your login password." + if Alert(self, message).launch(): + p = subprocess.run( + [ + "/usr/bin/pkexec", + "/usr/sbin/usermod", + "-a", + "-G", + "docker", + username, + ] + ) + if p.returncode == 0: + message = "Great! Now you must log out of your computer and log back in, and then you can use Dangerzone." + Alert(self, message).launch() + else: + message = "Failed to add your user to the 'docker' group, quitting." + Alert(self, message).launch() + + return False + + return True + def get_subprocess_startupinfo(self): if platform.system() == "Windows": startupinfo = subprocess.STARTUPINFO() @@ -358,3 +400,55 @@ class Common(object): return startupinfo else: return None + + +class Alert(QtWidgets.QDialog): + def __init__(self, common, message): + super(Alert, self).__init__() + self.common = common + + self.setWindowTitle("dangerzone") + self.setWindowIcon(self.common.get_window_icon()) + self.setModal(True) + + flags = ( + QtCore.Qt.CustomizeWindowHint + | QtCore.Qt.WindowTitleHint + | QtCore.Qt.WindowSystemMenuHint + | QtCore.Qt.WindowCloseButtonHint + | QtCore.Qt.WindowStaysOnTopHint + ) + self.setWindowFlags(flags) + + logo = QtWidgets.QLabel() + logo.setPixmap( + QtGui.QPixmap.fromImage( + QtGui.QImage(self.common.get_resource_path("icon.png")) + ) + ) + + label = QtWidgets.QLabel() + label.setText(message) + label.setWordWrap(True) + + message_layout = QtWidgets.QHBoxLayout() + message_layout.addWidget(logo) + message_layout.addWidget(label) + + ok_button = QtWidgets.QPushButton("Ok") + ok_button.clicked.connect(self.accept) + cancel_button = QtWidgets.QPushButton("Cancel") + cancel_button.clicked.connect(self.reject) + + buttons_layout = QtWidgets.QHBoxLayout() + buttons_layout.addStretch() + buttons_layout.addWidget(ok_button) + buttons_layout.addWidget(cancel_button) + + layout = QtWidgets.QVBoxLayout() + layout.addLayout(message_layout) + layout.addLayout(buttons_layout) + self.setLayout(layout) + + def launch(self): + return self.exec_() == QtWidgets.QDialog.Accepted diff --git a/stdeb.cfg b/stdeb.cfg index aff747a..cc6c6d6 100644 --- a/stdeb.cfg +++ b/stdeb.cfg @@ -1,6 +1,6 @@ [DEFAULT] Package3: dangerzone -Depends3: python3, python3-pyqt5, python3-appdirs, python3-click, python3-xdg +Depends3: docker.io, python3, python3-pyqt5, python3-appdirs, python3-click, python3-xdg Build-Depends: python3, python3-all Suite: bionic X-Python3-Version: >= 3.7 \ No newline at end of file From d8e17cb89894512515bbdedbbca38419bd9ebbec Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Feb 2020 15:39:22 -0800 Subject: [PATCH 2/3] Add debian deps that are required to build the .deb package --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index 0c30e80..46a4d7b 100644 --- a/BUILD.md +++ b/BUILD.md @@ -12,7 +12,7 @@ git submodule update Install dependencies: ```sh -sudo apt install -y docker.io python3 python3-pyqt5 python3-appdirs python3-click python3-xdg +sudo apt install -y python-all python3-stdeb docker.io python3 python3-pyqt5 python3-appdirs python3-click python3-xdg ``` Run from source tree: From 45f78637afbbdee925c021a14dc1573d2cccda62 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Feb 2020 16:04:11 -0800 Subject: [PATCH 3/3] Add build script and instructions for fedora --- BUILD.md | 20 +++++++++++++++ dangerzone/common.py | 2 +- install/linux/build_rpm.py | 52 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100755 install/linux/build_rpm.py diff --git a/BUILD.md b/BUILD.md index 46a4d7b..824f050 100644 --- a/BUILD.md +++ b/BUILD.md @@ -27,6 +27,26 @@ Create a .deb: ./install/linux/build_deb.py ``` +## Fedora + +Install dependencies: + +```sh +sudo dnf install -y rpm-build python3 python3-qt5 python3-appdirs python3-click +``` + +Run from source tree: + +```sh +./dev_script/dangerzone +``` + +Create a .rpm: + +```sh +./install/linux/build_rpm.py +``` + ## macOS Install Xcode from the Mac App Store. Once it's installed, run it for the first time to set it up. Also, run this to make sure command line tools are installed: `xcode-select --install`. And finally, open Xcode, go to Preferences > Locations, and make sure under Command Line Tools you select an installed version from the dropdown. (This is required for installing Qt5.) diff --git a/dangerzone/common.py b/dangerzone/common.py index 2da0ebe..9a2e449 100644 --- a/dangerzone/common.py +++ b/dangerzone/common.py @@ -68,7 +68,7 @@ class Common(object): # If this is fedora-like, use podman if os.path.exists("/usr/bin/dnf"): - self.container_runtime = "podman" + self.container_runtime = "/usr/bin/podman" # Otherwise, use docker else: self.container_runtime = "/usr/bin/docker" diff --git a/install/linux/build_rpm.py b/install/linux/build_rpm.py new file mode 100755 index 0000000..dc243da --- /dev/null +++ b/install/linux/build_rpm.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import os +import sys +import inspect +import subprocess +import shutil + +sys.path.insert( + 0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +) +import dangerzone + +version = dangerzone.dangerzone_version +root = os.path.dirname( + os.path.dirname( + os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + ) +) + + +def run(cmd): + subprocess.run(cmd, cwd=root, check=True) + + +def main(): + build_path = os.path.join(root, "build") + dist_path = os.path.join(root, "dist") + + print("* Deleting old build and dist") + if os.path.exists(build_path): + shutil.rmtree(build_path) + if os.path.exists(dist_path): + shutil.rmtree(dist_path) + + print("* Building RPM package") + run( + [ + "python3", + "setup.py", + "bdist_rpm", + "--requires=python3-qt5,python3-appdirs,python3-click", + ] + ) + + print("") + print("* To install run:") + print("sudo dnf install dist/dangerzone-{}-1.noarch.rpm".format(version)) + + +if __name__ == "__main__": + main()