From 7ece466d823ed876589071b4f652c4e6f89b1483 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Thu, 15 Oct 2020 19:09:46 -0700 Subject: Put tor binaries in desktop app resources, not cli resources, and fix Windows packaging --- .gitignore | 7 +- cli/onionshare_cli/onion.py | 6 +- cli/scripts/get-tor-osx.py | 126 ------------------------------ cli/scripts/get-tor-windows.py | 100 ------------------------ desktop/README.md | 49 +++++++++--- desktop/scripts/get-tor-osx.py | 126 ++++++++++++++++++++++++++++++ desktop/scripts/get-tor-windows.py | 100 ++++++++++++++++++++++++ desktop/src/onionshare/gui_common.py | 40 +++++++++- desktop/src/onionshare/settings_dialog.py | 2 +- 9 files changed, 312 insertions(+), 244 deletions(-) delete mode 100644 cli/scripts/get-tor-osx.py delete mode 100644 cli/scripts/get-tor-windows.py create mode 100644 desktop/scripts/get-tor-osx.py create mode 100644 desktop/scripts/get-tor-windows.py diff --git a/.gitignore b/.gitignore index 97ba1380..3c8d103d 100644 --- a/.gitignore +++ b/.gitignore @@ -56,8 +56,7 @@ venv # other .vscode onionshare.dist-info - -# Tor binaries -cli/onionshare_cli/resources/tor +desktop/src/onionshare/resources/tor +desktop/*.whl desktop/linux -desktop/windows \ No newline at end of file +desktop/windows diff --git a/cli/onionshare_cli/onion.py b/cli/onionshare_cli/onion.py index 5d08c1ed..02fd3263 100644 --- a/cli/onionshare_cli/onion.py +++ b/cli/onionshare_cli/onion.py @@ -152,7 +152,7 @@ class Onion(object): is necessary for status updates to reach the GUI. """ - def __init__(self, common, use_tmp_dir=False): + def __init__(self, common, use_tmp_dir=False, get_tor_paths=None): self.common = common self.common.log("Onion", "__init__") @@ -167,12 +167,14 @@ class Onion(object): self.bundle_tor_supported = True # Set the path of the tor binary, for bundled tor + if not get_tor_paths: + get_tor_paths = self.common.get_tor_paths ( self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path, - ) = self.common.get_tor_paths() + ) = get_tor_paths() # The tor process self.tor_proc = None diff --git a/cli/scripts/get-tor-osx.py b/cli/scripts/get-tor-osx.py deleted file mode 100644 index a05870f2..00000000 --- a/cli/scripts/get-tor-osx.py +++ /dev/null @@ -1,126 +0,0 @@ -# -*- coding: utf-8 -*- -""" -OnionShare | https://onionshare.org/ - -Copyright (C) 2014-2020 Micah Lee, et al. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -""" - -""" -This script downloads a pre-built tor binary to bundle with OnionShare. -In order to avoid a Mac gnupg dependency, I manually verify the signature -and hard-code the sha256 hash. -""" - -import inspect -import os -import sys -import hashlib -import zipfile -import io -import shutil -import subprocess -import requests - - -def main(): - dmg_url = "https://archive.torproject.org/tor-package-archive/torbrowser/10.0/TorBrowser-10.0-osx64_en-US.dmg" - dmg_filename = "TorBrowser-10.0-osx64_en-US.dmg" - expected_dmg_sha256 = ( - "4e1ca7068bc29d5e8ffba85ecc8fec36c52ae582faea67bcdf445cd57192fb08" - ) - - # Build paths - root_path = os.path.dirname( - os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) - ) - working_path = os.path.join(root_path, "build", "tor") - dmg_tor_path = os.path.join( - "/Volumes", "Tor Browser", "Tor Browser.app", "Contents" - ) - dmg_path = os.path.join(working_path, dmg_filename) - dist_path = os.path.join(root_path, "dist", "OnionShare.app", "Contents") - - # Make sure the working folder exists - if not os.path.exists(working_path): - os.makedirs(working_path) - - # Make sure the zip is downloaded - if not os.path.exists(dmg_path): - print("Downloading {}".format(dmg_url)) - r = requests.get(dmg_url) - open(dmg_path, "wb").write(r.content) - dmg_sha256 = hashlib.sha256(r.content).hexdigest() - else: - dmg_data = open(dmg_path, "rb").read() - dmg_sha256 = hashlib.sha256(dmg_data).hexdigest() - - # Compare the hash - if dmg_sha256 != expected_dmg_sha256: - print("ERROR! The sha256 doesn't match:") - print("expected: {}".format(expected_dmg_sha256)) - print(" actual: {}".format(dmg_sha256)) - sys.exit(-1) - - # Mount the dmg, copy data to the working path - subprocess.call(["hdiutil", "attach", dmg_path]) - - # Make sure Resources/tor exists before copying files - if os.path.exists(os.path.join(dist_path, "Resources", "Tor")): - shutil.rmtree(os.path.join(dist_path, "Resources", "Tor")) - os.makedirs(os.path.join(dist_path, "Resources", "Tor")) - if os.path.exists(os.path.join(dist_path, "MacOS", "Tor")): - shutil.rmtree(os.path.join(dist_path, "MacOS", "Tor")) - os.makedirs(os.path.join(dist_path, "MacOS", "Tor")) - - # Modify the tor script to adjust the path - tor_script = open( - os.path.join(dmg_tor_path, "Resources", "TorBrowser", "Tor", "tor"), "r" - ).read() - tor_script = tor_script.replace("../../../MacOS/Tor", "../../MacOS/Tor") - open(os.path.join(dist_path, "Resources", "Tor", "tor"), "w").write(tor_script) - - # Copy into dist - shutil.copyfile( - os.path.join(dmg_tor_path, "Resources", "TorBrowser", "Tor", "geoip"), - os.path.join(dist_path, "Resources", "Tor", "geoip"), - ) - shutil.copyfile( - os.path.join(dmg_tor_path, "Resources", "TorBrowser", "Tor", "geoip6"), - os.path.join(dist_path, "Resources", "Tor", "geoip6"), - ) - os.chmod(os.path.join(dist_path, "Resources", "Tor", "tor"), 0o755) - shutil.copyfile( - os.path.join(dmg_tor_path, "MacOS", "Tor", "tor.real"), - os.path.join(dist_path, "MacOS", "Tor", "tor.real"), - ) - shutil.copyfile( - os.path.join(dmg_tor_path, "MacOS", "Tor", "libevent-2.1.7.dylib"), - os.path.join(dist_path, "MacOS", "Tor", "libevent-2.1.7.dylib"), - ) - os.chmod(os.path.join(dist_path, "MacOS", "Tor", "tor.real"), 0o755) - # obfs4proxy binary - shutil.copyfile( - os.path.join(dmg_tor_path, "MacOS", "Tor", "PluggableTransports", "obfs4proxy"), - os.path.join(dist_path, "Resources", "Tor", "obfs4proxy"), - ) - os.chmod(os.path.join(dist_path, "Resources", "Tor", "obfs4proxy"), 0o755) - - # Eject dmg - subprocess.call(["diskutil", "eject", "/Volumes/Tor Browser"]) - - -if __name__ == "__main__": - main() diff --git a/cli/scripts/get-tor-windows.py b/cli/scripts/get-tor-windows.py deleted file mode 100644 index a5c4ebb1..00000000 --- a/cli/scripts/get-tor-windows.py +++ /dev/null @@ -1,100 +0,0 @@ -# -*- coding: utf-8 -*- -""" -OnionShare | https://onionshare.org/ - -Copyright (C) 2014-2020 Micah Lee, et al. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -""" - -""" -This script downloads a pre-built tor binary to bundle with OnionShare. -In order to avoid a Windows gnupg dependency, I manually verify the signature -and hard-code the sha256 hash. -""" - -import inspect -import os -import sys -import hashlib -import shutil -import subprocess -import requests - - -def main(): - exe_url = "https://archive.torproject.org/tor-package-archive/torbrowser/10.0/torbrowser-install-10.0_en-US.exe" - exe_filename = "torbrowser-install-10.0_en-US.exe" - expected_exe_sha256 = ( - "3d1a337da0e6eae32071e6de21963ba628a1a0939477bf823aa7df9051215410" - ) - # Build paths - root_path = os.path.dirname( - os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) - ) - working_path = os.path.join(root_path, "build", "tor") - exe_path = os.path.join(working_path, exe_filename) - dist_path = os.path.join(root_path, "onionshare_cli", "resources", "tor") - - # Make sure the working folder exists - if not os.path.exists(working_path): - os.makedirs(working_path) - - # Make sure Tor Browser is downloaded - if not os.path.exists(exe_path): - print("Downloading {}".format(exe_url)) - r = requests.get(exe_url) - open(exe_path, "wb").write(r.content) - exe_sha256 = hashlib.sha256(r.content).hexdigest() - else: - exe_data = open(exe_path, "rb").read() - exe_sha256 = hashlib.sha256(exe_data).hexdigest() - - # Compare the hash - if exe_sha256 != expected_exe_sha256: - print("ERROR! The sha256 doesn't match:") - print("expected: {}".format(expected_exe_sha256)) - print(" actual: {}".format(exe_sha256)) - sys.exit(-1) - - # Extract the bits we need from the exe - subprocess.Popen([ - "7z", - "e", - "-y", - exe_path, - "Browser\TorBrowser\Tor", - "-o%s" % os.path.join(working_path, "Tor"), - ]).wait() - subprocess.Popen([ - "7z", - "e", - "-y", - exe_path, - "Browser\TorBrowser\Data\Tor\geoip*", - "-o%s" % os.path.join(working_path, "Data"), - ]).wait() - - # Copy into the onionshare resources - if os.path.exists(dist_path): - shutil.rmtree(dist_path) - os.makedirs(dist_path) - shutil.copytree(os.path.join(working_path, "Tor"), os.path.join(dist_path, "Tor")) - shutil.copytree( - os.path.join(working_path, "Data"), os.path.join(dist_path, "Data", "Tor") - ) - - -if __name__ == "__main__": - main() diff --git a/desktop/README.md b/desktop/README.md index 91977fda..b1b36956 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -25,39 +25,39 @@ Download Python 3.8.6, 32-bit (x86) from https://www.python.org/downloads/releas Download and install 7-Zip from http://www.7-zip.org/download.html. I downloaded `7z1900.exe`. Add `C:\Program Files (x86)\7-Zip` to your path. -Install dependencies: - -``` -pip install requests -``` - Download Tor Browser and extract the binaries by running: ``` -cd ..\cli +pip install requests python scripts\get-tor-windows.py ``` ### Prepare the code +#### All platforms + OnionShare uses [Briefcase](https://briefcase.readthedocs.io/en/latest/). Install Briefcase dependencies by following [these instructions](https://docs.beeware.org/en/latest/tutorial/tutorial-0.html#install-dependencies). Now create and/or activate a virtual environment. +#### Linux and macOS + ``` python3 -m venv venv . venv/bin/activate ``` -Or in Windows: +#### Windows ``` python -m venv venv venv\Scripts\activate.bat ``` +#### All platforms + While your virtual environment is active, install briefcase from pip. ``` @@ -92,7 +92,9 @@ xvfb-run ./tests/run.sh ## Making a release -First, build a wheel package for OnionShare CLI: +### Linux + +Build a wheel package for OnionShare CLI: ```sh cd onionshare/cli @@ -115,4 +117,31 @@ Make sure the virtual environment is active, and then run `briefcase create` and . venv/bin/activate briefcase create briefcase build -``` \ No newline at end of file +``` + +### Windows + +Build a wheel package for OnionShare CLI (including Tor binaries, from Tor Browser): + +```sh +cd onionshare\cli +poetry install +poetry build +``` + +This will make a file like `dist\onionshare_cli-$VERSION-py3-none-any.whl` (except with your specific version number). Move it into `..\desktop`: + +``` +move dist\onionshare_cli-*-py3-none-any.whl ..\desktop +cd ..\desktop +``` + +Make sure the virtual environment is active, and then run `briefcase create`: + +```sh +venv\Scripts\activate.bat +briefcase create +briefcase package +``` + +TODO: Codesign \ No newline at end of file diff --git a/desktop/scripts/get-tor-osx.py b/desktop/scripts/get-tor-osx.py new file mode 100644 index 00000000..a05870f2 --- /dev/null +++ b/desktop/scripts/get-tor-osx.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +""" +OnionShare | https://onionshare.org/ + +Copyright (C) 2014-2020 Micah Lee, et al. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" + +""" +This script downloads a pre-built tor binary to bundle with OnionShare. +In order to avoid a Mac gnupg dependency, I manually verify the signature +and hard-code the sha256 hash. +""" + +import inspect +import os +import sys +import hashlib +import zipfile +import io +import shutil +import subprocess +import requests + + +def main(): + dmg_url = "https://archive.torproject.org/tor-package-archive/torbrowser/10.0/TorBrowser-10.0-osx64_en-US.dmg" + dmg_filename = "TorBrowser-10.0-osx64_en-US.dmg" + expected_dmg_sha256 = ( + "4e1ca7068bc29d5e8ffba85ecc8fec36c52ae582faea67bcdf445cd57192fb08" + ) + + # Build paths + root_path = os.path.dirname( + os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + ) + working_path = os.path.join(root_path, "build", "tor") + dmg_tor_path = os.path.join( + "/Volumes", "Tor Browser", "Tor Browser.app", "Contents" + ) + dmg_path = os.path.join(working_path, dmg_filename) + dist_path = os.path.join(root_path, "dist", "OnionShare.app", "Contents") + + # Make sure the working folder exists + if not os.path.exists(working_path): + os.makedirs(working_path) + + # Make sure the zip is downloaded + if not os.path.exists(dmg_path): + print("Downloading {}".format(dmg_url)) + r = requests.get(dmg_url) + open(dmg_path, "wb").write(r.content) + dmg_sha256 = hashlib.sha256(r.content).hexdigest() + else: + dmg_data = open(dmg_path, "rb").read() + dmg_sha256 = hashlib.sha256(dmg_data).hexdigest() + + # Compare the hash + if dmg_sha256 != expected_dmg_sha256: + print("ERROR! The sha256 doesn't match:") + print("expected: {}".format(expected_dmg_sha256)) + print(" actual: {}".format(dmg_sha256)) + sys.exit(-1) + + # Mount the dmg, copy data to the working path + subprocess.call(["hdiutil", "attach", dmg_path]) + + # Make sure Resources/tor exists before copying files + if os.path.exists(os.path.join(dist_path, "Resources", "Tor")): + shutil.rmtree(os.path.join(dist_path, "Resources", "Tor")) + os.makedirs(os.path.join(dist_path, "Resources", "Tor")) + if os.path.exists(os.path.join(dist_path, "MacOS", "Tor")): + shutil.rmtree(os.path.join(dist_path, "MacOS", "Tor")) + os.makedirs(os.path.join(dist_path, "MacOS", "Tor")) + + # Modify the tor script to adjust the path + tor_script = open( + os.path.join(dmg_tor_path, "Resources", "TorBrowser", "Tor", "tor"), "r" + ).read() + tor_script = tor_script.replace("../../../MacOS/Tor", "../../MacOS/Tor") + open(os.path.join(dist_path, "Resources", "Tor", "tor"), "w").write(tor_script) + + # Copy into dist + shutil.copyfile( + os.path.join(dmg_tor_path, "Resources", "TorBrowser", "Tor", "geoip"), + os.path.join(dist_path, "Resources", "Tor", "geoip"), + ) + shutil.copyfile( + os.path.join(dmg_tor_path, "Resources", "TorBrowser", "Tor", "geoip6"), + os.path.join(dist_path, "Resources", "Tor", "geoip6"), + ) + os.chmod(os.path.join(dist_path, "Resources", "Tor", "tor"), 0o755) + shutil.copyfile( + os.path.join(dmg_tor_path, "MacOS", "Tor", "tor.real"), + os.path.join(dist_path, "MacOS", "Tor", "tor.real"), + ) + shutil.copyfile( + os.path.join(dmg_tor_path, "MacOS", "Tor", "libevent-2.1.7.dylib"), + os.path.join(dist_path, "MacOS", "Tor", "libevent-2.1.7.dylib"), + ) + os.chmod(os.path.join(dist_path, "MacOS", "Tor", "tor.real"), 0o755) + # obfs4proxy binary + shutil.copyfile( + os.path.join(dmg_tor_path, "MacOS", "Tor", "PluggableTransports", "obfs4proxy"), + os.path.join(dist_path, "Resources", "Tor", "obfs4proxy"), + ) + os.chmod(os.path.join(dist_path, "Resources", "Tor", "obfs4proxy"), 0o755) + + # Eject dmg + subprocess.call(["diskutil", "eject", "/Volumes/Tor Browser"]) + + +if __name__ == "__main__": + main() diff --git a/desktop/scripts/get-tor-windows.py b/desktop/scripts/get-tor-windows.py new file mode 100644 index 00000000..33de056b --- /dev/null +++ b/desktop/scripts/get-tor-windows.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +""" +OnionShare | https://onionshare.org/ + +Copyright (C) 2014-2020 Micah Lee, et al. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" + +""" +This script downloads a pre-built tor binary to bundle with OnionShare. +In order to avoid a Windows gnupg dependency, I manually verify the signature +and hard-code the sha256 hash. +""" + +import inspect +import os +import sys +import hashlib +import shutil +import subprocess +import requests + + +def main(): + exe_url = "https://archive.torproject.org/tor-package-archive/torbrowser/10.0/torbrowser-install-10.0_en-US.exe" + exe_filename = "torbrowser-install-10.0_en-US.exe" + expected_exe_sha256 = ( + "3d1a337da0e6eae32071e6de21963ba628a1a0939477bf823aa7df9051215410" + ) + # Build paths + root_path = os.path.dirname( + os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + ) + working_path = os.path.join(root_path, "build", "tor") + exe_path = os.path.join(working_path, exe_filename) + dist_path = os.path.join(root_path, "src", "onionshare", "resources", "tor") + + # Make sure the working folder exists + if not os.path.exists(working_path): + os.makedirs(working_path) + + # Make sure Tor Browser is downloaded + if not os.path.exists(exe_path): + print("Downloading {}".format(exe_url)) + r = requests.get(exe_url) + open(exe_path, "wb").write(r.content) + exe_sha256 = hashlib.sha256(r.content).hexdigest() + else: + exe_data = open(exe_path, "rb").read() + exe_sha256 = hashlib.sha256(exe_data).hexdigest() + + # Compare the hash + if exe_sha256 != expected_exe_sha256: + print("ERROR! The sha256 doesn't match:") + print("expected: {}".format(expected_exe_sha256)) + print(" actual: {}".format(exe_sha256)) + sys.exit(-1) + + # Extract the bits we need from the exe + subprocess.Popen([ + "7z", + "e", + "-y", + exe_path, + "Browser\TorBrowser\Tor", + "-o%s" % os.path.join(working_path, "Tor"), + ]).wait() + subprocess.Popen([ + "7z", + "e", + "-y", + exe_path, + "Browser\TorBrowser\Data\Tor\geoip*", + "-o%s" % os.path.join(working_path, "Data"), + ]).wait() + + # Copy into the onionshare resources + if os.path.exists(dist_path): + shutil.rmtree(dist_path) + os.makedirs(dist_path) + shutil.copytree(os.path.join(working_path, "Tor"), os.path.join(dist_path, "Tor")) + shutil.copytree( + os.path.join(working_path, "Data"), os.path.join(dist_path, "Data", "Tor") + ) + + +if __name__ == "__main__": + main() diff --git a/desktop/src/onionshare/gui_common.py b/desktop/src/onionshare/gui_common.py index 1de82b3d..56e86067 100644 --- a/desktop/src/onionshare/gui_common.py +++ b/desktop/src/onionshare/gui_common.py @@ -50,7 +50,7 @@ class GuiCommon: strings.load_strings(self.common, self.get_resource_path("locale")) # Start the Onion - self.onion = Onion(common) + self.onion = Onion(common, get_tor_paths=self.get_tor_paths) # Lock filename self.lock_filename = os.path.join(self.common.build_data_dir(), "lock") @@ -328,6 +328,44 @@ class GuiCommon: font-style: italic; }""", } + + def get_tor_paths(self): + if self.common.platform == "Linux": + tor_path = shutil.which("tor") + obfs4proxy_file_path = shutil.which("obfs4proxy") + prefix = os.path.dirname(os.path.dirname(tor_path)) + tor_geo_ip_file_path = os.path.join(prefix, "share/tor/geoip") + tor_geo_ipv6_file_path = os.path.join(prefix, "share/tor/geoip6") + elif self.common.platform == "Windows": + base_path = self.get_resource_path("tor") + tor_path = os.path.join(base_path, "Tor", "tor.exe") + obfs4proxy_file_path = os.path.join(base_path, "Tor", "obfs4proxy.exe") + tor_geo_ip_file_path = os.path.join(base_path, "Data", "Tor", "geoip") + tor_geo_ipv6_file_path = os.path.join(base_path, "Data", "Tor", "geoip6") + elif self.common.platform == "Darwin": + base_path = os.path.dirname( + os.path.dirname(os.path.dirname(self.get_resource_path(""))) + ) + tor_path = os.path.join(base_path, "Resources", "Tor", "tor") + tor_geo_ip_file_path = os.path.join(base_path, "Resources", "Tor", "geoip") + tor_geo_ipv6_file_path = os.path.join( + base_path, "Resources", "Tor", "geoip6" + ) + obfs4proxy_file_path = os.path.join( + base_path, "Resources", "Tor", "obfs4proxy" + ) + elif self.common.platform == "BSD": + tor_path = "/usr/local/bin/tor" + tor_geo_ip_file_path = "/usr/local/share/tor/geoip" + tor_geo_ipv6_file_path = "/usr/local/share/tor/geoip6" + obfs4proxy_file_path = "/usr/local/bin/obfs4proxy" + + return ( + tor_path, + tor_geo_ip_file_path, + tor_geo_ipv6_file_path, + obfs4proxy_file_path, + ) @staticmethod def get_resource_path(filename): diff --git a/desktop/src/onionshare/settings_dialog.py b/desktop/src/onionshare/settings_dialog.py index cb4033f5..e1027323 100644 --- a/desktop/src/onionshare/settings_dialog.py +++ b/desktop/src/onionshare/settings_dialog.py @@ -665,7 +665,7 @@ class SettingsDialog(QtWidgets.QDialog): else: tor_status_update_func = None - onion = Onion(self.common, use_tmp_dir=True) + onion = Onion(self.common, use_tmp_dir=True, get_tor_paths=self.common.gui.get_tor_paths) onion.connect( custom_settings=settings, tor_status_update_func=tor_status_update_func, ) -- cgit v1.2.3-54-g00ecf