Various safety checks to prevent a share from starting after the timeout has expired. Also enforce that a timeout lands right on the minute and not precisely when the user clicks start (e.g mid-minute), to avoid confusion that a share might be lingering longer than desired

This commit is contained in:
Miguel Jacq 2017-11-09 17:26:32 +11:00
parent 9aabc51edc
commit ac0e375a4b
No known key found for this signature in database
GPG key ID: EEA4341C6D97A0B6
3 changed files with 37 additions and 7 deletions

View file

@ -316,14 +316,18 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.filesize_warning.setText(strings._("large_filesize", True)) self.filesize_warning.setText(strings._("large_filesize", True))
self.filesize_warning.show() self.filesize_warning.show()
if self.server_status.server_shutdown_timeout_checkbox.isChecked(): if self.server_status.timer_enabled:
# Convert the date value to seconds between now and then # Convert the date value to seconds between now and then
now = QtCore.QDateTime.currentDateTime() now = QtCore.QDateTime.currentDateTime()
self.timeout = now.secsTo(self.server_status.server_shutdown_timeout.dateTime()) self.timeout = now.secsTo(self.server_status.timeout)
# Set the shutdown timeout value # Set the shutdown timeout value
if self.timeout > 0: if self.timeout > 0:
self.app.shutdown_timer = common.close_after_seconds(self.timeout) self.app.shutdown_timer = common.close_after_seconds(self.timeout)
self.app.shutdown_timer.start() self.app.shutdown_timer.start()
# The timeout has actually already passed since the user clicked Start. Probably the Onion service took too long to start.
else:
self.stop_server()
self.start_server_error(strings._('gui_server_started_after_timeout'))
def start_server_error(self, error): def start_server_error(self, error):
""" """
@ -383,10 +387,11 @@ class OnionShareGui(QtWidgets.QMainWindow):
# If the auto-shutdown timer has stopped, stop the server # If the auto-shutdown timer has stopped, stop the server
if self.server_status.status == self.server_status.STATUS_STARTED: if self.server_status.status == self.server_status.STATUS_STARTED:
if self.app.shutdown_timer and self.timeout > 0: if self.app.shutdown_timer and self.server_status.timer_enabled and self.timeout > 0:
if not self.app.shutdown_timer.is_alive(): if not self.app.shutdown_timer.is_alive():
self.stop_server() self.stop_server()
self.status_bar.showMessage(strings._('close_on_timeout',True)) self.status_bar.showMessage(strings._('close_on_timeout',True))
self.server_status.shutdown_timeout_reset()
# scroll to the bottom of the dl progress bar log pane # scroll to the bottom of the dl progress bar log pane
# if a new download has been added # if a new download has been added
@ -432,6 +437,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
# close on finish? # close on finish?
if not web.get_stay_open(): if not web.get_stay_open():
self.server_status.stop_server() self.server_status.stop_server()
self.server_status.shutdown_timeout_reset()
elif event["type"] == web.REQUEST_CANCELED: elif event["type"] == web.REQUEST_CANCELED:
self.downloads.cancel_download(event["data"]["id"]) self.downloads.cancel_download(event["data"]["id"])

View file

@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import platform import platform
from .alert import Alert
from PyQt5 import QtCore, QtWidgets, QtGui from PyQt5 import QtCore, QtWidgets, QtGui
from onionshare import strings, common from onionshare import strings, common
@ -44,15 +45,19 @@ class ServerStatus(QtWidgets.QVBoxLayout):
self.web = web self.web = web
self.file_selection = file_selection self.file_selection = file_selection
# shutdown timeout layout # Helper boolean as this is used in a few places
self.timer_enabled = False
# Shutdown timeout layout
self.server_shutdown_timeout_checkbox = QtWidgets.QCheckBox() self.server_shutdown_timeout_checkbox = QtWidgets.QCheckBox()
self.server_shutdown_timeout_checkbox.setCheckState(QtCore.Qt.Unchecked) self.server_shutdown_timeout_checkbox.setCheckState(QtCore.Qt.Unchecked)
self.server_shutdown_timeout_checkbox.toggled.connect(self.shutdown_timeout_toggled) self.server_shutdown_timeout_checkbox.toggled.connect(self.shutdown_timeout_toggled)
self.server_shutdown_timeout_checkbox.setText(strings._("gui_settings_shutdown_timeout_choice", True)) self.server_shutdown_timeout_checkbox.setText(strings._("gui_settings_shutdown_timeout_choice", True))
self.server_shutdown_timeout_label = QtWidgets.QLabel(strings._('gui_settings_shutdown_timeout', True)) self.server_shutdown_timeout_label = QtWidgets.QLabel(strings._('gui_settings_shutdown_timeout', True))
self.server_shutdown_timeout = QtWidgets.QDateTimeEdit() self.server_shutdown_timeout = QtWidgets.QDateTimeEdit()
# Set proposed timeout to be 5 minutes into the future
self.server_shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(300)) self.server_shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(300))
self.server_shutdown_timeout.setMinimumDateTime(QtCore.QDateTime.currentDateTime()) # Onion services can take a little while to start, so reduce the risk of it expiring too soon by setting the minimum to 2 min from now
self.server_shutdown_timeout.setMinimumDateTime(QtCore.QDateTime.currentDateTime().addSecs(120))
self.server_shutdown_timeout.setCurrentSectionIndex(4) self.server_shutdown_timeout.setCurrentSectionIndex(4)
self.server_shutdown_timeout_label.hide() self.server_shutdown_timeout_label.hide()
self.server_shutdown_timeout.hide() self.server_shutdown_timeout.hide()
@ -99,16 +104,26 @@ class ServerStatus(QtWidgets.QVBoxLayout):
Shutdown timer option was toggled. If checked, hide the option and show the timer settings. Shutdown timer option was toggled. If checked, hide the option and show the timer settings.
""" """
if checked: if checked:
self.timer_enabled = True
# Hide the checkbox, show the options
self.server_shutdown_timeout_checkbox.hide() self.server_shutdown_timeout_checkbox.hide()
self.server_shutdown_timeout_label.show() self.server_shutdown_timeout_label.show()
# Reset the default timer to 5 minutes into the future after toggling the option on # Reset the default timer to 5 minutes into the future after toggling the option on
self.server_shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(300)) self.server_shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(300))
self.server_shutdown_timeout.show() self.server_shutdown_timeout.show()
else: else:
self.timer_enabled = False
self.server_shutdown_timeout_checkbox.show() self.server_shutdown_timeout_checkbox.show()
self.server_shutdown_timeout_label.hide() self.server_shutdown_timeout_label.hide()
self.server_shutdown_timeout.hide() self.server_shutdown_timeout.hide()
def shutdown_timeout_reset(self):
"""
Reset the timeout in the UI after stopping a share
"""
self.server_shutdown_timeout.setDateTime(QtCore.QDateTime.currentDateTime().addSecs(300))
self.server_shutdown_timeout.setMinimumDateTime(QtCore.QDateTime.currentDateTime().addSecs(120))
def update(self): def update(self):
""" """
Update the GUI elements based on the current state. Update the GUI elements based on the current state.
@ -171,9 +186,16 @@ class ServerStatus(QtWidgets.QVBoxLayout):
Toggle starting or stopping the server. Toggle starting or stopping the server.
""" """
if self.status == self.STATUS_STOPPED: if self.status == self.STATUS_STOPPED:
self.start_server() # Get the timeout chosen, stripped of its seconds. This prevents confusion if the share stops at (say) 37 seconds past the minute chosen
self.timeout = self.server_shutdown_timeout.dateTime().toPyDateTime().replace(second=0, microsecond=0)
# If the timeout has actually passed already before the user hit Start, refuse to start the server.
if QtCore.QDateTime.currentDateTime().toPyDateTime() > self.timeout:
Alert(strings._('gui_server_timeout_expired', QtWidgets.QMessageBox.Warning))
else:
self.start_server()
elif self.status == self.STATUS_STARTED: elif self.status == self.STATUS_STARTED:
self.stop_server() self.stop_server()
self.shutdown_timeout_reset()
def start_server(self): def start_server(self):
""" """

View file

@ -115,5 +115,7 @@
"gui_tor_connection_ask": "Would you like to open OnionShare settings to troubleshoot connecting to Tor?", "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_open_settings": "Open Settings",
"gui_tor_connection_ask_quit": "Quit", "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_error_settings": "Try adjusting how OnionShare connects to the Tor network in Settings.",
"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."
} }