diff --git a/onionshare/onion.py b/onionshare/onion.py index 02f062fb..a3aee7a5 100644 --- a/onionshare/onion.py +++ b/onionshare/onion.py @@ -375,6 +375,17 @@ class Onion(object): # ephemeral stealth onion services are not supported self.supports_stealth = False + + def is_authenticated(self): + """ + Returns True if the Tor connection is still working, or False otherwise. + """ + if self.c is not None: + return self.c.is_authenticated() + else: + return False + + def start_onion_service(self, port): """ Start a onion service on port 80, pointing to the given port, and diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index 71a4843a..c056a32d 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -130,23 +130,25 @@ class OnionShareGui(QtWidgets.QMainWindow): self.setCentralWidget(central_widget) self.show() - # Check for requests frequently - self.timer = QtCore.QTimer() - self.timer.timeout.connect(self.check_for_requests) - self.timer.start(500) - # Always start with focus on file selection self.file_selection.setFocus() # The server isn't active yet self.set_server_active(False) + # Create the timer + self.timer = QtCore.QTimer() + self.timer.timeout.connect(self.check_for_requests) + # 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() + # Start the timer + self.timer.start(500) + # After connecting to Tor, check for updates self.check_for_updates() @@ -219,6 +221,17 @@ class OnionShareGui(QtWidgets.QMainWindow): def reload_settings(): common.log('OnionShareGui', 'open_settings', 'settings have changed, reloading') self.settings.load() + # We might've stopped the main requests timer if a Tor connection failed. + # If we've reloaded settings, we probably succeeded in obtaining a new + # connection. If so, restart the timer. + if self.onion.is_authenticated(): + if not self.timer.isActive(): + self.timer.start(500) + # If there were some files listed for sharing, we should be ok to + # re-enable the 'Start Sharing' button now. + if self.server_status.file_selection.get_num_files() > 0: + self.server_status.server_button.setEnabled(True) + self.status_bar.clearMessage() d = SettingsDialog(self.onion, self.qtapp, self.config) d.settings_saved.connect(reload_settings) @@ -398,6 +411,16 @@ class OnionShareGui(QtWidgets.QMainWindow): """ self.update() + # Have we lost connection to Tor somehow? + if not self.onion.is_authenticated(): + self.timer.stop() + if self.server_status.status != self.server_status.STATUS_STOPPED: + self.server_status.stop_server() + self.server_status.server_button.setEnabled(False) + self.status_bar.showMessage(strings._('gui_tor_connection_lost', True)) + if self.systemTray.supportsMessages() and self.settings.get('systray_notifications'): + self.systemTray.showMessage(strings._('gui_tor_connection_lost', True), strings._('gui_tor_connection_error_settings', True)) + # scroll to the bottom of the dl progress bar log pane # if a new download has been added if self.new_download: diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index b9534511..6542a8d5 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -461,7 +461,8 @@ class SettingsDialog(QtWidgets.QDialog): # If Tor isn't connected, or if Tor settings have changed, Reinitialize # the Onion object reboot_onion = False - if self.onion.connected_to_tor: + if self.onion.is_authenticated(): + common.log('SettingsDialog', 'save_clicked', 'Connected to Tor') def changed(s1, s2, keys): """ Compare the Settings objects s1 and s2 and return true if any values @@ -480,6 +481,7 @@ class SettingsDialog(QtWidgets.QDialog): reboot_onion = True else: + common.log('SettingsDialog', 'save_clicked', 'Not connected to Tor') # Tor isn't connected, so try connecting reboot_onion = True @@ -494,7 +496,7 @@ class SettingsDialog(QtWidgets.QDialog): 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(): + if self.onion.is_authenticated() and not tor_con.wasCanceled(): self.settings_saved.emit() self.close() @@ -507,7 +509,7 @@ class SettingsDialog(QtWidgets.QDialog): Cancel button clicked. """ common.log('SettingsDialog', 'cancel_clicked') - if not self.onion.connected_to_tor: + if not self.onion.is_authenticated(): Alert(strings._('gui_tor_connection_canceled', True), QtWidgets.QMessageBox.Warning) sys.exit() else: @@ -562,7 +564,7 @@ class SettingsDialog(QtWidgets.QDialog): common.log('SettingsDialog', 'closeEvent') # On close, if Tor isn't connected, then quit OnionShare altogether - if not self.onion.connected_to_tor: + if not self.onion.is_authenticated(): common.log('SettingsDialog', 'closeEvent', 'Closing while not connected to Tor') # Wait 1ms for the event loop to finish, then quit diff --git a/onionshare_gui/tor_connection_dialog.py b/onionshare_gui/tor_connection_dialog.py index fa4c7860..dc472725 100644 --- a/onionshare_gui/tor_connection_dialog.py +++ b/onionshare_gui/tor_connection_dialog.py @@ -64,7 +64,7 @@ class TorConnectionDialog(QtWidgets.QProgressDialog): t.error_connecting_to_tor.connect(self._error_connecting_to_tor) t.start() - # The main thread needs to remain active, and checkign for Qt events, + # The main thread needs to remain active, and checking for Qt events, # until the thread is finished. Otherwise it won't be able to handle # accepting signals. self.active = True @@ -86,6 +86,7 @@ class TorConnectionDialog(QtWidgets.QProgressDialog): def _canceled_connecting_to_tor(self): common.log('TorConnectionDialog', '_canceled_connecting_to_tor') self.active = False + self.onion.cleanup() # Cancel connecting to Tor QtCore.QTimer.singleShot(1, self.cancel) diff --git a/share/locale/en.json b/share/locale/en.json index 0756843e..abd734c9 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -119,6 +119,7 @@ "gui_tor_connection_ask_quit": "Quit", "gui_tor_connection_error_settings": "Try adjusting how OnionShare connects to the Tor network in Settings.", "gui_tor_connection_canceled": "OnionShare cannot connect to Tor.\n\nMake sure you're connected to the internet, then re-open OnionShare to configure the Tor connection.", + "gui_tor_connection_lost": "Disconnected from Tor.", "gui_server_started_after_timeout": "The server started after your chosen auto-timeout.\nPlease start a new share.", "gui_server_timeout_expired": "The chosen timeout has already expired.\nPlease update the timeout and then you may start sharing.", "share_via_onionshare": "Share via OnionShare"