diff --git a/onionshare/web.py b/onionshare/web.py index 762e2342..f0d8f532 100644 --- a/onionshare/web.py +++ b/onionshare/web.py @@ -50,6 +50,7 @@ class Web(object): REQUEST_OTHER = 3 REQUEST_CANCELED = 4 REQUEST_RATE_LIMIT = 5 + REQUEST_CLOSE_SERVER = 6 def __init__(self, common, gui_mode, receive_mode=False): self.common = common @@ -118,6 +119,9 @@ class Web(object): # shutting down the server only works within the context of flask, so the easiest way to do it is over http self.shutdown_slug = self.common.random_string(16) + # Keep track if the server is running + self.running = False + # Define the ewb app routes self.common_routes() if self.receive_mode: @@ -331,6 +335,7 @@ class Web(object): if self.common.settings.get('receive_allow_receiver_shutdown'): self.force_shutdown() r = make_response(render_template('closed.html')) + self.add_request(self.REQUEST_CLOSE_SERVER, request.path) return self.add_security_headers(r) else: return redirect('/{}'.format(slug_candidate)) @@ -451,11 +456,12 @@ class Web(object): """ Stop the flask web server, from the context of the flask app. """ - # shutdown the flask service + # Shutdown the flask service func = request.environ.get('werkzeug.server.shutdown') if func is None: raise RuntimeError('Not running with the Werkzeug Server') func() + self.running = False def start(self, port, stay_open=False, persistent_slug=None): """ @@ -472,6 +478,7 @@ class Web(object): else: host = '127.0.0.1' + self.running = True self.app.run(host=host, port=port, threaded=True) def stop(self, port): @@ -483,16 +490,17 @@ class Web(object): # serving the file self.client_cancel = True - # to stop flask, load http://127.0.0.1://shutdown - try: - s = socket.socket() - s.connect(('127.0.0.1', port)) - s.sendall('GET /{0:s}/shutdown HTTP/1.1\r\n\r\n'.format(self.shutdown_slug)) - except: + # To stop flask, load http://127.0.0.1://shutdown + if self.running: try: - urlopen('http://127.0.0.1:{0:d}/{1:s}/shutdown'.format(port, self.shutdown_slug)).read() + s = socket.socket() + s.connect(('127.0.0.1', port)) + s.sendall('GET /{0:s}/shutdown HTTP/1.1\r\n\r\n'.format(self.shutdown_slug)) except: - pass + try: + urlopen('http://127.0.0.1:{0:d}/{1:s}/shutdown'.format(port, self.shutdown_slug)).read() + except: + pass class ZipWriter(object): diff --git a/onionshare_gui/mode.py b/onionshare_gui/mode.py index 9ff0ee76..cca2254d 100644 --- a/onionshare_gui/mode.py +++ b/onionshare_gui/mode.py @@ -284,3 +284,41 @@ class Mode(QtWidgets.QWidget): Add custom initialization here. """ pass + + # Handle web server events + + def handle_request_load(self, event): + """ + Handle REQUEST_LOAD event. + """ + pass + + def handle_request_download(self, event): + """ + Handle REQUEST_DOWNLOAD event. + """ + pass + + def handle_request_rate_limit(self, event): + """ + Handle REQUEST_RATE_LIMIT event. + """ + pass + + def handle_request_progress(self, event): + """ + Handle REQUEST_PROGRESS event. + """ + pass + + def handle_request_canceled(self, event): + """ + Handle REQUEST_CANCELED event. + """ + pass + + def handle_request_close_server(self, event): + """ + Handle REQUEST_CLOSE_SERVER event. + """ + pass diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py index f223ff3c..f0820ac4 100644 --- a/onionshare_gui/onionshare_gui.py +++ b/onionshare_gui/onionshare_gui.py @@ -382,41 +382,43 @@ class OnionShareGui(QtWidgets.QMainWindow): # Process events from the web object if self.mode == self.MODE_SHARE: - web = self.share_mode.web + mode = self.share_mode else: - web = self.receive_mode.web + mode = self.receive_mode events = [] done = False while not done: try: - r = web.q.get(False) + r = mode.web.q.get(False) events.append(r) except queue.Empty: done = True for event in events: if event["type"] == Web.REQUEST_LOAD: - self.share_mode.handle_request_load(event) + mode.handle_request_load(event) elif event["type"] == Web.REQUEST_DOWNLOAD: - self.share_mode.handle_request_download(event) + mode.handle_request_download(event) elif event["type"] == Web.REQUEST_RATE_LIMIT: - self.share_mode.handle_request_rate_limit(event) + mode.handle_request_rate_limit(event) elif event["type"] == Web.REQUEST_PROGRESS: - self.share_mode.handle_request_progress(event) + mode.handle_request_progress(event) elif event["type"] == Web.REQUEST_CANCELED: - self.share_mode.handle_request_canceled(event) + mode.handle_request_canceled(event) + + elif event["type"] == Web.REQUEST_CLOSE_SERVER: + mode.handle_request_close_server(event) elif event["path"] != '/favicon.ico': - self.status_bar.showMessage('[#{0:d}] {1:s}: {2:s}'.format(web.error404_count, strings._('other_page_loaded', True), event["path"])) + self.status_bar.showMessage('[#{0:d}] {1:s}: {2:s}'.format(mode.web.error404_count, strings._('other_page_loaded', True), event["path"])) - self.share_mode.timer_callback() - self.receive_mode.timer_callback() + mode.timer_callback() def copy_url(self): """ diff --git a/onionshare_gui/receive_mode/__init__.py b/onionshare_gui/receive_mode/__init__.py index 2b7a6295..5b65a052 100644 --- a/onionshare_gui/receive_mode/__init__.py +++ b/onionshare_gui/receive_mode/__init__.py @@ -92,3 +92,10 @@ class ReceiveMode(Mode): # Continue self.starting_server_step3.emit() self.start_server_finished.emit() + + def handle_request_close_server(self, event): + """ + Handle REQUEST_CLOSE_SERVER event. + """ + self.stop_server() + self.system_tray.showMessage(strings._('systray_close_server_title', True), strings._('systray_close_server_message', True)) diff --git a/share/locale/en.json b/share/locale/en.json index d6f325bb..08678747 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -179,5 +179,7 @@ "gui_settings_downloads_label": "Save files to", "gui_settings_downloads_button": "Browse", "gui_settings_receive_allow_receiver_shutdown_checkbox": "Allow people who upload files to you to stop Receive Mode for you", - "gui_settings_receive_public_mode_checkbox": "Receive Mode is open to the public\n(don't try to prevent people from guessing the OnionShare address)" + "gui_settings_receive_public_mode_checkbox": "Receive Mode is open to the public\n(don't try to prevent people from guessing the OnionShare address)", + "systray_close_server_title": "OnionShare Server Closed", + "systray_close_server_message": "The user closed the server" }