summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMicah Lee <micah@micahflee.com>2020-12-13 11:40:25 -0800
committerMicah Lee <micah@micahflee.com>2020-12-13 11:40:25 -0800
commitb96b83905ba5b62c332a6c8946218ddae4c61517 (patch)
treef5a8fb5ade60583e12d07c657fde007c8ffe4ce0
parentae621b4001dc44d7f07a9fad43376439b855ccd8 (diff)
parenta520057bf4bd0956f03b763bfacdb8145cb5f977 (diff)
downloadonionshare-b96b83905ba5b62c332a6c8946218ddae4c61517.tar.gz
onionshare-b96b83905ba5b62c332a6c8946218ddae4c61517.zip
Merge branch 'develop' into 929_download_errors
-rw-r--r--cli/onionshare_cli/__init__.py14
-rw-r--r--cli/onionshare_cli/common.py10
-rw-r--r--cli/onionshare_cli/onion.py129
-rw-r--r--cli/onionshare_cli/onionshare.py1
-rw-r--r--desktop/README.md31
-rw-r--r--desktop/scripts/dev.bat3
-rwxr-xr-xdesktop/scripts/dev.sh9
-rwxr-xr-xdesktop/scripts/rebuild-cli.py45
-rw-r--r--desktop/src/onionshare/gui_common.py53
-rw-r--r--desktop/src/onionshare/resources/locale/en.json3
-rw-r--r--desktop/src/onionshare/settings_dialog.py40
-rw-r--r--desktop/src/onionshare/tab/mode/__init__.py3
-rw-r--r--desktop/src/onionshare/tab/tab.py14
-rw-r--r--desktop/src/onionshare/threads.py14
-rw-r--r--desktop/src/onionshare/tor_connection_dialog.py41
15 files changed, 294 insertions, 116 deletions
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 <http://www.gnu.org/licenses/>.
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 <http://www.gnu.org/licenses/>.
"""
+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)