diff --git a/cli/onionshare_cli/__init__.py b/cli/onionshare_cli/__init__.py index 12808375..8ba0aac2 100644 --- a/cli/onionshare_cli/__init__.py +++ b/cli/onionshare_cli/__init__.py @@ -22,7 +22,7 @@ import os, sys, time, argparse, threading from datetime import datetime from datetime import timedelta -from .common import Common +from .common import Common, CannotFindTor from .web import Web from .onion import * from .onionshare import OnionShare @@ -320,7 +320,15 @@ def main(cwd=None): web = Web(common, False, mode_settings, mode) # Start the Onion object - onion = Onion(common, use_tmp_dir=True) + try: + onion = Onion(common, use_tmp_dir=True) + except CannotFindTor: + print("You must install tor to use OnionShare from the command line") + if common.platform == "Darwin": + print("In macOS, you can do this with Homebrew (https://brew.sh):") + print(" brew install tor") + sys.exit() + try: onion.connect( custom_settings=False, @@ -332,7 +340,7 @@ def main(cwd=None): print("") sys.exit() except Exception as e: - sys.exit(e.args[0]) + sys.exit() # Start the onionshare app try: diff --git a/cli/onionshare_cli/common.py b/cli/onionshare_cli/common.py index a1213387..e8b174b6 100644 --- a/cli/onionshare_cli/common.py +++ b/cli/onionshare_cli/common.py @@ -34,6 +34,12 @@ from pkg_resources import resource_filename from .settings import Settings +class CannotFindTor(Exception): + """ + OnionShare can't find a tor binary + """ + + class Common: """ The Common object is shared amongst all parts of OnionShare. @@ -82,6 +88,8 @@ class Common: def get_tor_paths(self): if self.platform == "Linux": tor_path = shutil.which("tor") + if not tor_path: + raise CannotFindTor() 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") @@ -94,6 +102,8 @@ class Common: tor_geo_ipv6_file_path = os.path.join(base_path, "Data", "Tor", "geoip6") elif self.platform == "Darwin": tor_path = shutil.which("tor") + if not tor_path: + raise CannotFindTor() 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") diff --git a/cli/onionshare_cli/onion.py b/cli/onionshare_cli/onion.py index 56a19133..7c9d0a67 100644 --- a/cli/onionshare_cli/onion.py +++ b/cli/onionshare_cli/onion.py @@ -32,11 +32,8 @@ import getpass import psutil from distutils.version import LooseVersion as Version -from . import common from .settings import Settings -# TODO: Figure out how to localize this for the GUI - class TorErrorAutomatic(Exception): """ @@ -44,40 +41,30 @@ class TorErrorAutomatic(Exception): using automatic settings that should work with Tor Browser. """ - pass - class TorErrorInvalidSetting(Exception): """ This exception is raised if the settings just don't make sense. """ - pass - class TorErrorSocketPort(Exception): """ OnionShare can't connect to the Tor controller using the supplied address and port. """ - pass - class TorErrorSocketFile(Exception): """ OnionShare can't connect to the Tor controller using the supplied socket file. """ - pass - class TorErrorMissingPassword(Exception): """ OnionShare connected to the Tor controller, but it requires a password. """ - pass - class TorErrorUnreadableCookieFile(Exception): """ @@ -85,8 +72,6 @@ class TorErrorUnreadableCookieFile(Exception): to access the cookie file. """ - pass - class TorErrorAuthError(Exception): """ @@ -94,8 +79,6 @@ class TorErrorAuthError(Exception): that a Tor controller isn't listening on this port. """ - pass - class TorErrorProtocolError(Exception): """ @@ -103,17 +86,17 @@ class TorErrorProtocolError(Exception): isn't acting like a Tor controller (such as in Whonix). """ - pass - -class TorTooOld(Exception): +class TorTooOldEphemeral(Exception): """ - This exception is raised if onionshare needs to use a feature of Tor or stem - (like stealth ephemeral onion services) but the version you have installed - is too old. + This exception is raised if the version of tor doesn't support ephemeral onion services """ - pass + +class TorTooOldStealth(Exception): + """ + This exception is raised if the version of tor doesn't support stealth onion services + """ class BundledTorTimeout(Exception): @@ -137,6 +120,12 @@ class BundledTorBroken(Exception): """ +class PortNotAvailable(Exception): + """ + There are no available ports for OnionShare to use, which really shouldn't ever happen + """ + + class Onion(object): """ Onion is an abstraction layer for connecting to the Tor control port and @@ -236,7 +225,8 @@ class Onion(object): try: self.tor_socks_port = self.common.get_available_port(1000, 65535) except: - raise OSError("OnionShare port not available") + print("OnionShare port not available") + raise PortNotAvailable() self.tor_torrc = os.path.join(self.tor_data_directory_name, "torrc") # If there is an existing OnionShare tor process, kill it @@ -268,7 +258,8 @@ class Onion(object): try: self.tor_control_port = self.common.get_available_port(1000, 65535) except: - raise OSError("OnionShare port not available") + print("OnionShare port not available") + raise PortNotAvailable() self.tor_control_socket = None else: # Linux and BSD can use unix sockets @@ -337,10 +328,6 @@ class Onion(object): f.write(self.settings.get("tor_bridges_use_custom_bridges")) f.write("\nUseBridges 1") - # Make sure the tor path is accurate - if not os.path.exists(self.tor_path): - raise BundledTorNotSupported(f"Cannot find tor binary: {self.tor_path}") - # Execute a tor subprocess start_ts = time.time() if self.common.platform == "Windows": @@ -375,10 +362,8 @@ class Onion(object): self.c = Controller.from_socket_file(path=self.tor_control_socket) self.c.authenticate() except Exception as e: - raise BundledTorBroken( - # strings._("settings_error_bundled_tor_broken").format(e.args[0]) - "OnionShare could not connect to Tor:\n{}".format(e.args[0]) - ) + print("OnionShare could not connect to Tor:\n{}".format(e.args[0])) + raise BundledTorBroken(e.args[0]) while True: try: @@ -425,15 +410,16 @@ class Onion(object): print("") try: self.tor_proc.terminate() - raise BundledTorTimeout( - # strings._("settings_error_bundled_tor_timeout") + print( "Taking too long to connect to Tor. Maybe you aren't connected to the Internet, or have an inaccurate system clock?" ) + raise BundledTorTimeout() except FileNotFoundError: pass elif self.settings.get("connection_type") == "automatic": # Automatically try to guess the right way to connect to Tor Browser + automatic_error = "Could not connect to the Tor controller. Is Tor Browser (available from torproject.org) running in the background?" # Try connecting to control port found_tor = False @@ -485,30 +471,25 @@ class Onion(object): ) elif self.common.platform == "Windows": # Windows doesn't support unix sockets - raise TorErrorAutomatic( - # strings._("settings_error_automatic") - "Could not connect to the Tor controller. Is Tor Browser (available from torproject.org) running in the background?" - ) + print(automatic_error) + raise TorErrorAutomatic() self.c = Controller.from_socket_file(path=socket_file_path) except: - raise TorErrorAutomatic( - # strings._("settings_error_automatic") - "Could not connect to the Tor controller. Is Tor Browser (available from torproject.org) running in the background?" - ) + print(automatic_error) + raise TorErrorAutomatic() # Try authenticating try: self.c.authenticate() except: - raise TorErrorAutomatic( - # strings._("settings_error_automatic") - "Could not connect to the Tor controller. Is Tor Browser (available from torproject.org) running in the background?" - ) + print(automatic_error) + raise TorErrorAutomatic() else: # Use specific settings to connect to tor + invalid_settings_error = "Can't connect to Tor controller because your settings don't make sense." # Try connecting try: @@ -522,27 +503,28 @@ class Onion(object): path=self.settings.get("socket_file_path") ) else: - raise TorErrorInvalidSetting( - # strings._("settings_error_unknown") - "Can't connect to Tor controller because your settings don't make sense." - ) + print(invalid_settings_error) + raise TorErrorInvalidSetting() except: if self.settings.get("connection_type") == "control_port": - raise TorErrorSocketPort( - # strings._("settings_error_socket_port") + print( "Can't connect to the Tor controller at {}:{}.".format( self.settings.get("control_port_address"), self.settings.get("control_port_port"), ) ) + raise TorErrorSocketPort( + self.settings.get("control_port_address"), + self.settings.get("control_port_port"), + ) else: - raise TorErrorSocketFile( - # strings._("settings_error_socket_file") + print( "Can't connect to the Tor controller using socket file {}.".format( self.settings.get("socket_file_path") ) ) + raise TorErrorSocketFile(self.settings.get("socket_file_path")) # Try authenticating try: @@ -551,29 +533,30 @@ class Onion(object): elif self.settings.get("auth_type") == "password": self.c.authenticate(self.settings.get("auth_password")) else: - raise TorErrorInvalidSetting( - # strings._("settings_error_unknown") - "Can't connect to Tor controller because your settings don't make sense." - ) + print(invalid_settings_error) + raise TorErrorInvalidSetting() except MissingPassword: - raise TorErrorMissingPassword( - # strings._("settings_error_missing_password") + print( "Connected to Tor controller, but it requires a password to authenticate." ) + raise TorErrorMissingPassword() except UnreadableCookieFile: - raise TorErrorUnreadableCookieFile( - # strings._("settings_error_unreadable_cookie_file") + print( "Connected to the Tor controller, but password may be wrong, or your user is not permitted to read the cookie file." ) + raise TorErrorUnreadableCookieFile() except AuthenticationFailure: - raise TorErrorAuthError( - # strings._("settings_error_auth") + print( "Connected to {}:{}, but can't authenticate. Maybe this isn't a Tor controller?".format( self.settings.get("control_port_address"), self.settings.get("control_port_port"), ) ) + raise TorErrorAuthError( + self.settings.get("control_port_address"), + self.settings.get("control_port_port"), + ) # If we made it this far, we should be connected to Tor self.connected_to_tor = True @@ -628,15 +611,15 @@ class Onion(object): self.common.log("Onion", "start_onion_service", f"port={port}") if not self.supports_ephemeral: - raise TorTooOld( - # strings._("error_ephemeral_not_supported") + print( "Your version of Tor is too old, ephemeral onion services are not supported" ) + raise TorTooOldEphemeral() if mode_settings.get("general", "client_auth") and not self.supports_stealth: - raise TorTooOld( - # strings._("error_stealth_not_supported") + print( "Your version of Tor is too old, stealth onion services are not supported" ) + raise TorTooOldStealth() auth_cookie = None if mode_settings.get("general", "client_auth"): @@ -693,10 +676,8 @@ class Onion(object): ) except ProtocolError as e: - raise TorErrorProtocolError( - # strings._("error_tor_protocol_error") - "Tor error: {}".format(e.args[0]) - ) + print("Tor error: {}".format(e.args[0])) + raise TorErrorProtocolError(e.args[0]) onion_host = res.service_id + ".onion" diff --git a/cli/onionshare_cli/onionshare.py b/cli/onionshare_cli/onionshare.py index 6fead913..db15a03d 100644 --- a/cli/onionshare_cli/onionshare.py +++ b/cli/onionshare_cli/onionshare.py @@ -21,7 +21,6 @@ along with this program. If not, see . import os, shutil from . import common -from .onion import TorTooOld, TorErrorProtocolError from .common import AutoStopTimer diff --git a/desktop/README.md b/desktop/README.md index 039124fe..97d0fd30 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -51,17 +51,7 @@ Download Tor Browser and extract the binaries: python scripts\get-tor-windows.py ``` -### Prepare the code - -In order to work with the desktop app, you'll need to build a wheel of the CLI package first, and copy it into the `desktop` folder: - -```sh -cd ../cli -poetry install -poetry build -cp dist/onionshare_cli-*.whl ../desktop -cd ../desktop -``` +### Prepare the virtual environment OnionShare uses [Briefcase](https://briefcase.readthedocs.io/en/latest/). @@ -86,19 +76,30 @@ While your virtual environment is active, install briefcase from pip. pip install briefcase ``` -Run OnionShare from the source tree like this (`-d` re-installs dependencies, which you'll have to do each time you update the `onionshare-cli` wheel): +In order to work with the desktop app, you'll need to build a wheel of the CLI package first, and copy it into the `desktop` folder. You'll need to re-run this script each time you change the CLI code. + +```sh +python scripts/rebuild-cli.py +``` + +### Running OnionShare from the source code tree + +Inside the virtual environment, run OnionShare like this to install all of the dependencies: ``` briefcase dev -d ``` -If you want to pass arguments into `onionshare`, such as to use verbose mode: +Once you have the dependencies installed, you can run it using the `dev.sh` script, which lets you use command line arguments, such as to `--verbose` or `--local-only`: ``` -cd src -python -c "import onionshare; onionshare.main()" --help +./scripts/dev.sh --help +./scripts/dev.sh -v +./scripts/dev.sh -v --local-only ``` +Windows uses `scripts\dev.bat` instead. + ## Running tests Install these packages inside your virtual environment: diff --git a/desktop/scripts/dev.bat b/desktop/scripts/dev.bat new file mode 100644 index 00000000..9b537a90 --- /dev/null +++ b/desktop/scripts/dev.bat @@ -0,0 +1,3 @@ +cd src +python -c "import onionshare; onionshare.main()" %* +cd .. \ No newline at end of file diff --git a/desktop/scripts/dev.sh b/desktop/scripts/dev.sh new file mode 100755 index 00000000..6ce5e796 --- /dev/null +++ b/desktop/scripts/dev.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Run OnionShare desktop, allowing you to use command-line arguments + +SCRIPTS_DIR="$( cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )" +cd $SCRIPTS_DIR + +cd ../src +python -c "import onionshare; onionshare.main()" $@ \ No newline at end of file diff --git a/desktop/scripts/rebuild-cli.py b/desktop/scripts/rebuild-cli.py new file mode 100755 index 00000000..c13461bc --- /dev/null +++ b/desktop/scripts/rebuild-cli.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +""" +This script builds the CLI python wheel, copies it to the desktop folder, +and installs it in the virtual environment. +""" + +import inspect +import os +import sys +import glob +import subprocess +import shutil + + +def main(): + # Build paths + root_path = os.path.dirname( + os.path.dirname( + os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + ) + ) + cli_path = os.path.join(root_path, "cli") + desktop_path = os.path.join(root_path, "desktop") + + # Delete old wheels + for filename in glob.glob(os.path.join(cli_path, "dist", "*.whl")): + os.remove(filename) + + # Build new wheel + subprocess.call(["poetry", "install"], cwd=cli_path) + subprocess.call(["poetry", "build"], cwd=cli_path) + wheel_filename = glob.glob(os.path.join(cli_path, "dist", "*.whl"))[0] + wheel_basename = os.path.basename(wheel_filename) + shutil.copyfile( + wheel_filename, + os.path.join(desktop_path, wheel_basename), + ) + + # Reinstall the new wheel + subprocess.call(["pip", "uninstall", "onionshare-cli", "-y"]) + subprocess.call(["pip", "install", os.path.join(desktop_path, wheel_basename)]) + + +if __name__ == "__main__": + main() diff --git a/desktop/src/onionshare/gui_common.py b/desktop/src/onionshare/gui_common.py index f488a740..7d367b99 100644 --- a/desktop/src/onionshare/gui_common.py +++ b/desktop/src/onionshare/gui_common.py @@ -24,7 +24,22 @@ import shutil from pkg_resources import resource_filename from . import strings -from onionshare_cli.onion import Onion +from onionshare_cli.onion import ( + Onion, + TorErrorInvalidSetting, + TorErrorAutomatic, + TorErrorSocketPort, + TorErrorSocketFile, + TorErrorMissingPassword, + TorErrorUnreadableCookieFile, + TorErrorAuthError, + TorErrorProtocolError, + BundledTorTimeout, + BundledTorBroken, + TorTooOldEphemeral, + TorTooOldStealth, + PortNotAvailable, +) class GuiCommon: @@ -245,7 +260,7 @@ class GuiCommon: QLabel { text-align: center; color: #333333; - font-size: 28px; + font-size: 25px; } """, # Share mode and child widget styles @@ -377,3 +392,37 @@ class GuiCommon: Returns the absolute path of a resource """ return resource_filename("onionshare", os.path.join("resources", filename)) + + @staticmethod + def get_translated_tor_error(e): + """ + Takes an exception defined in onion.py and returns a translated error message + """ + if type(e) is TorErrorInvalidSetting: + return strings._("settings_error_unknown") + elif type(e) is TorErrorAutomatic: + return strings._("settings_error_automatic") + elif type(e) is TorErrorSocketPort: + return strings._("settings_error_socket_port").format(e.args[0], e.args[1]) + elif type(e) is TorErrorSocketFile: + return strings._("settings_error_socket_file").format(e.args[0]) + elif type(e) is TorErrorMissingPassword: + return strings._("settings_error_missing_password") + elif type(e) is TorErrorUnreadableCookieFile: + return strings._("settings_error_unreadable_cookie_file") + elif type(e) is TorErrorAuthError: + return strings._("settings_error_auth").format(e.args[0], e.args[1]) + elif type(e) is TorErrorProtocolError: + return strings._("error_tor_protocol_error").format(e.args[0]) + elif type(e) is BundledTorTimeout: + return strings._("settings_error_bundled_tor_timeout") + elif type(e) is BundledTorBroken: + return strings._("settings_error_bundled_tor_broken").format(e.args[0]) + elif type(e) is TorTooOldEphemeral: + return strings._("error_ephemeral_not_supported") + elif type(e) is TorTooOldStealth: + return strings._("error_stealth_not_supported") + elif type(e) is PortNotAvailable: + return strings._("error_port_not_available") + + return None diff --git a/desktop/src/onionshare/resources/locale/en.json b/desktop/src/onionshare/resources/locale/en.json index 81984273..502fe13e 100644 --- a/desktop/src/onionshare/resources/locale/en.json +++ b/desktop/src/onionshare/resources/locale/en.json @@ -189,5 +189,6 @@ "settings_error_bundled_tor_timeout": "Taking too long to connect to Tor. Maybe you aren't connected to the Internet, or have an inaccurate system clock?", "settings_error_bundled_tor_broken": "OnionShare could not connect to Tor:\n{}", "gui_rendezvous_cleanup": "Waiting for Tor circuits to close to be sure your files have successfully transferred.\n\nThis might take a few minutes.", - "gui_rendezvous_cleanup_quit_early": "Quit Early" + "gui_rendezvous_cleanup_quit_early": "Quit Early", + "error_port_not_available": "OnionShare port not available" } \ No newline at end of file diff --git a/desktop/src/onionshare/settings_dialog.py b/desktop/src/onionshare/settings_dialog.py index 5f37bda1..974b7008 100644 --- a/desktop/src/onionshare/settings_dialog.py +++ b/desktop/src/onionshare/settings_dialog.py @@ -27,11 +27,31 @@ import os from onionshare_cli import common from onionshare_cli.settings import Settings -from onionshare_cli.onion import * +from onionshare_cli.onion import ( + Onion, + TorErrorInvalidSetting, + TorErrorAutomatic, + TorErrorSocketPort, + TorErrorSocketFile, + TorErrorMissingPassword, + TorErrorUnreadableCookieFile, + TorErrorAuthError, + TorErrorProtocolError, + BundledTorTimeout, + BundledTorBroken, + TorTooOldEphemeral, + TorTooOldStealth, + PortNotAvailable, +) from . import strings from .widgets import Alert -from .update_checker import * +from .update_checker import ( + UpdateCheckerCheckError, + UpdateCheckerInvalidLatestVersion, + UpdateChecker, + UpdateThread, +) from .tor_connection_dialog import TorConnectionDialog from .gui_common import GuiCommon @@ -142,7 +162,7 @@ class SettingsDialog(QtWidgets.QDialog): self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path, - ) = self.common.get_tor_paths() + ) = self.common.gui.get_tor_paths() if not self.obfs4proxy_file_path or not os.path.isfile( self.obfs4proxy_file_path ): @@ -165,7 +185,7 @@ class SettingsDialog(QtWidgets.QDialog): self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path, - ) = self.common.get_tor_paths() + ) = self.common.gui.get_tor_paths() if not self.obfs4proxy_file_path or not os.path.isfile( self.obfs4proxy_file_path ): @@ -698,10 +718,18 @@ class SettingsDialog(QtWidgets.QDialog): TorErrorUnreadableCookieFile, TorErrorAuthError, TorErrorProtocolError, - BundledTorNotSupported, BundledTorTimeout, + BundledTorBroken, + TorTooOldEphemeral, + TorTooOldStealth, + PortNotAvailable, ) as e: - Alert(self.common, e.args[0], QtWidgets.QMessageBox.Warning) + message = self.common.gui.get_translated_tor_error(e) + Alert( + self.common, + message, + QtWidgets.QMessageBox.Warning, + ) if settings.get("connection_type") == "bundled": self.tor_status.hide() self._enable_buttons() diff --git a/desktop/src/onionshare/tab/mode/__init__.py b/desktop/src/onionshare/tab/mode/__init__.py index 7738f567..0bef7628 100644 --- a/desktop/src/onionshare/tab/mode/__init__.py +++ b/desktop/src/onionshare/tab/mode/__init__.py @@ -183,8 +183,7 @@ class Mode(QtWidgets.QWidget): self.status_bar.clearMessage() if not self.app.autostop_timer_thread.is_alive(): - if self.autostop_timer_finished_should_stop_server(): - self.server_status.stop_server() + self.autostop_timer_finished_should_stop_server() def timer_callback_custom(self): """ diff --git a/desktop/src/onionshare/tab/tab.py b/desktop/src/onionshare/tab/tab.py index f474b9ba..8cbddfed 100644 --- a/desktop/src/onionshare/tab/tab.py +++ b/desktop/src/onionshare/tab/tab.py @@ -53,16 +53,22 @@ class NewTabButton(QtWidgets.QPushButton): ) self.image_label.setAlignment(QtCore.Qt.AlignCenter) self.image_label.setStyleSheet(self.common.gui.css["new_tab_button_image"]) - self.image_label.setGeometry(0, 0, self.width(), 200) + self.image_label.setGeometry(0, 0, self.width(), 190) self.image_label.show() # Title self.title_label = QtWidgets.QLabel(title, parent=self) + self.title_label.setWordWrap(True) self.title_label.setAlignment(QtCore.Qt.AlignCenter) self.title_label.setStyleSheet(self.common.gui.css["new_tab_title_text"]) - self.title_label.setGeometry( - (self.width() - 250) / 2, self.height() - 100, 250, 30 - ) + if self.title_label.sizeHint().width() >= 250: + self.title_label.setGeometry( + (self.width() - 250) / 2, self.height() - 120, 250, 60 + ) + else: + self.title_label.setGeometry( + (self.width() - 250) / 2, self.height() - 100, 250, 30 + ) self.title_label.show() # Text diff --git a/desktop/src/onionshare/threads.py b/desktop/src/onionshare/threads.py index 22e264e5..0c31a838 100644 --- a/desktop/src/onionshare/threads.py +++ b/desktop/src/onionshare/threads.py @@ -24,7 +24,6 @@ import os from PySide2 import QtCore from onionshare_cli.onion import ( - TorTooOld, TorErrorInvalidSetting, TorErrorAutomatic, TorErrorSocketPort, @@ -34,6 +33,10 @@ from onionshare_cli.onion import ( TorErrorAuthError, TorErrorProtocolError, BundledTorTimeout, + BundledTorBroken, + TorTooOldEphemeral, + TorTooOldStealth, + PortNotAvailable, ) from . import strings @@ -93,7 +96,6 @@ class OnionThread(QtCore.QThread): self.success.emit() except ( - TorTooOld, TorErrorInvalidSetting, TorErrorAutomatic, TorErrorSocketPort, @@ -103,9 +105,13 @@ class OnionThread(QtCore.QThread): TorErrorAuthError, TorErrorProtocolError, BundledTorTimeout, - OSError, + BundledTorBroken, + TorTooOldEphemeral, + TorTooOldStealth, + PortNotAvailable, ) as e: - self.error.emit(e.args[0]) + message = self.mode.common.gui.get_translated_tor_error(e) + self.error.emit(message) return diff --git a/desktop/src/onionshare/tor_connection_dialog.py b/desktop/src/onionshare/tor_connection_dialog.py index d5fa72a0..a9201aed 100644 --- a/desktop/src/onionshare/tor_connection_dialog.py +++ b/desktop/src/onionshare/tor_connection_dialog.py @@ -18,9 +18,25 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ +import time from PySide2 import QtCore, QtWidgets, QtGui -from onionshare_cli.onion import * +from onionshare_cli.onion import ( + BundledTorCanceled, + TorErrorInvalidSetting, + TorErrorAutomatic, + TorErrorSocketPort, + TorErrorSocketFile, + TorErrorMissingPassword, + TorErrorUnreadableCookieFile, + TorErrorAuthError, + TorErrorProtocolError, + BundledTorTimeout, + BundledTorBroken, + TorTooOldEphemeral, + TorTooOldStealth, + PortNotAvailable, +) from . import strings from .gui_common import GuiCommon @@ -156,9 +172,26 @@ class TorConnectionThread(QtCore.QThread): ) self.canceled_connecting_to_tor.emit() - except Exception as e: - self.common.log("TorConnectionThread", "run", f"caught exception: {e}") - self.error_connecting_to_tor.emit(str(e)) + except ( + TorErrorInvalidSetting, + TorErrorAutomatic, + TorErrorSocketPort, + TorErrorSocketFile, + TorErrorMissingPassword, + TorErrorUnreadableCookieFile, + TorErrorAuthError, + TorErrorProtocolError, + BundledTorTimeout, + BundledTorBroken, + TorTooOldEphemeral, + TorTooOldStealth, + PortNotAvailable, + ) as e: + message = self.common.gui.get_translated_tor_error(e) + self.common.log( + "TorConnectionThread", "run", f"caught exception: {message}" + ) + self.error_connecting_to_tor.emit(message) def _tor_status_update(self, progress, summary): self.tor_status_update.emit(progress, summary)