When saving settings, if Tor settings changed or if Tor isn't connected, reboot the Onion object, so that it's always connected to Tor when using the app

This commit is contained in:
Micah Lee 2017-05-16 16:50:33 -07:00
parent eb708973c8
commit 010bddb066
No known key found for this signature in database
GPG Key ID: 403C2657CD994F73
5 changed files with 110 additions and 44 deletions

View File

@ -417,6 +417,11 @@ class Onion(object):
self.tor_proc.kill()
self.tor_proc = None
# Reset other Onion settings
self.connected_to_tor = False
self.stealth = False
self.service_id = None
def get_tor_socks_port(self):
"""
Returns a (address, port) tuple for the Tor SOCKS port

View File

@ -59,12 +59,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.settings = Settings()
self.settings.load()
# Start the "Connecting to Tor" dialog, which calls onion.connect()
tor_con = TorConnectionDialog(self.qtapp, self.settings, self.onion)
tor_con.canceled.connect(self._tor_connection_canceled)
tor_con.open_settings.connect(self._tor_connection_open_settings)
tor_con.start()
# Check for updates in a new thread, if enabled
system = platform.system()
if system == 'Windows' or system == 'Darwin':
@ -151,6 +145,12 @@ class OnionShareGui(QtWidgets.QMainWindow):
# The server isn't active yet
self.set_server_active(False)
# Start the "Connecting to Tor" dialog, which calls onion.connect()
tor_con = TorConnectionDialog(self.qtapp, self.settings, self.onion)
tor_con.canceled.connect(self._tor_connection_canceled)
tor_con.open_settings.connect(self._tor_connection_open_settings)
tor_con.start()
def _tor_connection_canceled(self):
"""
If the user cancels before Tor finishes connecting, ask if they want to
@ -158,22 +158,29 @@ class OnionShareGui(QtWidgets.QMainWindow):
"""
common.log('OnionShareGui', '_tor_connection_canceled')
def quit_settings_dialog():
a = Alert("Would you like to open OnionShare settings to troubleshoot connecting to Tor?", QtWidgets.QMessageBox.Question, buttons=QtWidgets.QMessageBox.NoButton, autostart=False)
settings_button = QtWidgets.QPushButton("Open Settings")
quit_button = QtWidgets.QPushButton("Quit")
def ask():
a = Alert(strings._('gui_tor_connection_ask', True), QtWidgets.QMessageBox.Question, buttons=QtWidgets.QMessageBox.NoButton, autostart=False)
settings_button = QtWidgets.QPushButton(strings._('gui_tor_connection_ask_open_settings', True))
quit_button = QtWidgets.QPushButton(strings._('gui_tor_connection_ask_quit', True))
a.addButton(settings_button, QtWidgets.QMessageBox.AcceptRole)
a.addButton(quit_button, QtWidgets.QMessageBox.RejectRole)
a.setDefaultButton(settings_button)
a.exec_()
if a.clickedButton() == settings_button:
# Open settings
common.log('OnionShareGui', '_tor_connection_canceled', 'Settings button clicked')
self.open_settings()
else:
self.qtapp.quit()
# Wait 1ms for the event loop to finish closing the TorConnectionDialog
QtCore.QTimer.singleShot(1, quit_settings_dialog)
if a.clickedButton() == quit_button:
# Quit
common.log('OnionShareGui', '_tor_connection_canceled', 'Quit button clicked')
# Wait 1ms for the event loop to finish, then quit
QtCore.QTimer.singleShot(1, self.qtapp.quit)
# Wait 100ms before asking
QtCore.QTimer.singleShot(100, ask)
def _tor_connection_open_settings(self):
"""

View File

@ -26,6 +26,7 @@ from onionshare.onion import *
from .alert import Alert
from .update_checker import *
from .tor_connection_dialog import TorConnectionDialog
class SettingsDialog(QtWidgets.QDialog):
"""
@ -229,31 +230,31 @@ class SettingsDialog(QtWidgets.QDialog):
self.cancel_button.setFocus()
# Load settings, and fill them in
settings = Settings()
settings.load()
self.old_settings = Settings()
self.old_settings.load()
close_after_first_download = settings.get('close_after_first_download')
close_after_first_download = self.old_settings.get('close_after_first_download')
if close_after_first_download:
self.close_after_first_download_checkbox.setCheckState(QtCore.Qt.Checked)
else:
self.close_after_first_download_checkbox.setCheckState(QtCore.Qt.Unchecked)
use_stealth = settings.get('use_stealth')
use_stealth = self.old_settings.get('use_stealth')
if use_stealth:
self.stealth_checkbox.setCheckState(QtCore.Qt.Checked)
else:
self.stealth_checkbox.setCheckState(QtCore.Qt.Unchecked)
use_autoupdate = settings.get('use_autoupdate')
use_autoupdate = self.old_settings.get('use_autoupdate')
if use_autoupdate:
self.autoupdate_checkbox.setCheckState(QtCore.Qt.Checked)
else:
self.autoupdate_checkbox.setCheckState(QtCore.Qt.Unchecked)
autoupdate_timestamp = settings.get('autoupdate_timestamp')
autoupdate_timestamp = self.old_settings.get('autoupdate_timestamp')
self._update_autoupdate_timestamp(autoupdate_timestamp)
connection_type = settings.get('connection_type')
connection_type = self.old_settings.get('connection_type')
if connection_type == 'bundled':
if self.connection_type_bundled_radio.isEnabled():
self.connection_type_bundled_radio.setChecked(True)
@ -266,17 +267,17 @@ class SettingsDialog(QtWidgets.QDialog):
self.connection_type_control_port_radio.setChecked(True)
elif connection_type == 'socket_file':
self.connection_type_socket_file_radio.setChecked(True)
self.connection_type_control_port_extras_address.setText(settings.get('control_port_address'))
self.connection_type_control_port_extras_port.setText(str(settings.get('control_port_port')))
self.connection_type_socket_file_extras_path.setText(settings.get('socket_file_path'))
self.connection_type_socks_address.setText(settings.get('socks_address'))
self.connection_type_socks_port.setText(str(settings.get('socks_port')))
auth_type = settings.get('auth_type')
self.connection_type_control_port_extras_address.setText(self.old_settings.get('control_port_address'))
self.connection_type_control_port_extras_port.setText(str(self.old_settings.get('control_port_port')))
self.connection_type_socket_file_extras_path.setText(self.old_settings.get('socket_file_path'))
self.connection_type_socks_address.setText(self.old_settings.get('socks_address'))
self.connection_type_socks_port.setText(str(self.old_settings.get('socks_port')))
auth_type = self.old_settings.get('auth_type')
if auth_type == 'no_auth':
self.authenticate_no_auth_radio.setChecked(True)
elif auth_type == 'password':
self.authenticate_password_radio.setChecked(True)
self.authenticate_password_extras_password.setText(settings.get('auth_password'))
self.authenticate_password_extras_password.setText(self.old_settings.get('auth_password'))
# Show the dialog
self.exec_()
@ -421,7 +422,48 @@ class SettingsDialog(QtWidgets.QDialog):
settings = self.settings_from_fields()
settings.save()
self.close()
# If Tor isn't connected, or if Tor settings have changed, Reinitialize
# the Onion object
reboot_onion = False
if self.onion.connected_to_tor:
def changed(s1, s2, keys):
"""
Compare the Settings objects s1 and s2 and return true if any values
have changed for the given keys.
"""
for key in keys:
if s1.get(key) != s2.get(key):
return True
return False
if changed(settings, self.old_settings, [
'connection_type', 'control_port_address',
'control_port_port', 'socks_address', 'socks_port',
'socket_file_path', 'auth_type', 'auth_password']):
reboot_onion = True
else:
# Tor isn't connected, so try connecting
reboot_onion = True
# Do we need to reinitialize Tor?
if reboot_onion:
# Reinitialize the Onion object
common.log('SettingsDialog', 'save_clicked', 'rebooting the Onion')
self.onion.cleanup()
tor_con = TorConnectionDialog(self.qtapp, settings, self.onion)
tor_con.start()
common.log('SettingsDialog', 'save_clicked', 'Onion done rebooting, connected to Tor: {}'.format(self.onion.connected_to_tor))
if self.onion.connected_to_tor and not tor_con.wasCanceled():
self.close()
else:
self.close()
def cancel_clicked(self):
"""
@ -466,6 +508,16 @@ class SettingsDialog(QtWidgets.QDialog):
return settings
def closeEvent(self, e):
common.log('SettingsDialog', 'closeEvent')
# On close, if Tor isn't connected, then quit OnionShare altogether
if not self.onion.connected_to_tor:
common.log('SettingsDialog', 'closeEvent', 'Closing while not connected to Tor')
# Wait 1ms for the event loop to finish, then quit
QtCore.QTimer.singleShot(1, self.qtapp.quit)
def _update_autoupdate_timestamp(self, autoupdate_timestamp):
common.log('SettingsDialog', '_update_autoupdate_timestamp')

View File

@ -38,7 +38,7 @@ class TorConnectionDialog(QtWidgets.QProgressDialog):
self.settings = settings
self.onion = onion
self.setWindowTitle("OnionShare")
self.setWindowTitle("OnionShare TOR")
self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png')))
self.setModal(True)
self.setFixedSize(400, 150)
@ -88,20 +88,23 @@ class TorConnectionDialog(QtWidgets.QProgressDialog):
self.active = False
# Cancel connecting to Tor
self.cancel()
QtCore.QTimer.singleShot(1, self.cancel)
def _error_connecting_to_tor(self, msg):
common.log('TorConnectionDialog', '_error_connecting_to_tor')
self.active = False
def alert_and_open_settings():
# Display the exception in an alert box
Alert("{}\n\n{}".format(msg, strings._('gui_tor_connection_error_settings', True)), QtWidgets.QMessageBox.Warning)
# Open settings
self.open_settings.emit()
QtCore.QTimer.singleShot(1, alert_and_open_settings)
# Cancel connecting to Tor
self.cancel()
# Display the exception in an alert box
Alert("{}\n\n{}".format(msg, strings._('gui_tor_connection_error_settings', True)), QtWidgets.QMessageBox.Warning)
# Open settings
self.open_settings.emit()
QtCore.QTimer.singleShot(1, self.cancel)
class TorConnectionThread(QtCore.QThread):
tor_status_update = QtCore.pyqtSignal(str, str)
@ -126,11 +129,11 @@ class TorConnectionThread(QtCore.QThread):
if self.onion.connected_to_tor:
self.connected_to_tor.emit()
else:
self.error_connecting_to_tor.emit(strings._('settings_error_unknown_error', True))
self.canceled_connecting_to_tor.emit()
except BundledTorCanceled as e:
common.log('TorConnectionThread', 'run', 'caught exception: BundledTorCanceled')
self.canceled_connecting_to_tor.emit(strings._('settings_error_bundled_tor_canceled'))
self.canceled_connecting_to_tor.emit()
except Exception as e:
common.log('TorConnectionThread', 'run', 'caught exception: {}'.format(e.args[0]))

View File

@ -52,9 +52,6 @@
"zip_progress_bar_format": "Crunching files: %p%",
"error_stealth_not_supported": "To create stealth onion services, you need at least Tor 0.2.9.1-alpha (or Tor Browser 6.5) and at least python3-stem 1.5.0.",
"error_ephemeral_not_supported": "OnionShare requires at least at least Tor 0.2.7.1 and at least python3-stem 1.4.0.",
"gui_menu_file_menu": "&File",
"gui_menu_settings_action": "&Settings",
"gui_menu_quit_action": "&Quit",
"gui_settings_window_title": "Settings",
"gui_settings_stealth_label": "Stealth (advanced)",
"gui_settings_stealth_option": "Create stealth onion services",
@ -94,7 +91,6 @@
"settings_error_bundled_tor_not_supported": "Bundled Tor is not supported when not using developer mode in Windows or macOS.",
"settings_error_bundled_tor_timeout": "Connecting to Tor is taking too long. Maybe your computer is offline, or your clock isn't accurate.",
"settings_error_bundled_tor_canceled": "The Tor process closed before it could finish connecting.",
"settings_error_unknown_error": "Failed connecting to Tor for an unknown reasons.",
"settings_test_success": "Congratulations, OnionShare can connect to the Tor controller.\n\nTor version: {}\nSupports ephemeral onion services: {}\nSupports stealth onion services: {}",
"error_tor_protocol_error": "Error talking to the Tor controller.\nIf you're using Whonix, check out https://www.whonix.org/wiki/onionshare to make OnionShare work.",
"connecting_to_tor": "Connecting to the Tor network",
@ -102,5 +98,8 @@
"update_error_check_error": "Error checking for updates: Maybe you're not connected to Tor, or maybe the OnionShare website is down.",
"update_error_invalid_latest_version": "Error checking for updates: The OnionShare website responded saying the latest version is '{}', but that doesn't appear to be a valid version string.",
"update_not_available": "You are running the latest version of OnionShare.",
"gui_tor_connection_ask": "Would you like to open OnionShare settings to troubleshoot connecting to Tor?",
"gui_tor_connection_ask_open_settings": "Open Settings",
"gui_tor_connection_ask_quit": "Quit",
"gui_tor_connection_error_settings": "Try adjusting how OnionShare connects to the Tor network in Settings."
}