diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py
index 39b75449..53858eeb 100644
--- a/onionshare_gui/onionshare_gui.py
+++ b/onionshare_gui/onionshare_gui.py
@@ -125,95 +125,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.update_mode_switcher()
- # File selection
- self.file_selection = FileSelection(self.common)
- if filenames:
- for filename in filenames:
- self.file_selection.file_list.add_file(filename)
-
- # Server status
- self.server_status = ServerStatus(self.common, self.qtapp, self.app, self.web, self.file_selection)
- self.server_status.server_started.connect(self.file_selection.server_started)
- self.server_status.server_started.connect(self.start_server)
- self.server_status.server_started.connect(self.update_server_status_indicator)
- self.server_status.server_stopped.connect(self.file_selection.server_stopped)
- self.server_status.server_stopped.connect(self.stop_server)
- self.server_status.server_stopped.connect(self.update_server_status_indicator)
- self.server_status.server_stopped.connect(self.update_primary_action)
- self.server_status.server_canceled.connect(self.cancel_server)
- self.server_status.server_canceled.connect(self.file_selection.server_stopped)
- self.server_status.server_canceled.connect(self.update_primary_action)
- self.start_server_finished.connect(self.clear_message)
- self.start_server_finished.connect(self.server_status.start_server_finished)
- self.start_server_finished.connect(self.update_server_status_indicator)
- self.stop_server_finished.connect(self.server_status.stop_server_finished)
- self.stop_server_finished.connect(self.update_server_status_indicator)
- self.file_selection.file_list.files_updated.connect(self.server_status.update)
- self.file_selection.file_list.files_updated.connect(self.update_primary_action)
- self.server_status.url_copied.connect(self.copy_url)
- self.server_status.hidservauth_copied.connect(self.copy_hidservauth)
- self.starting_server_step2.connect(self.start_server_step2)
- self.starting_server_step3.connect(self.start_server_step3)
- self.starting_server_error.connect(self.start_server_error)
- self.server_status.button_clicked.connect(self.clear_message)
-
- # Filesize warning
- self.filesize_warning = QtWidgets.QLabel()
- self.filesize_warning.setWordWrap(True)
- self.filesize_warning.setStyleSheet('padding: 10px 0; font-weight: bold; color: #333333;')
- self.filesize_warning.hide()
-
- # Downloads
- self.downloads = Downloads(self.common)
- self.new_download = False
- self.downloads_in_progress = 0
- self.downloads_completed = 0
-
- # Info label along top of screen
- self.info_layout = QtWidgets.QHBoxLayout()
- self.info_label = QtWidgets.QLabel()
- self.info_label.setStyleSheet('QLabel { font-size: 12px; color: #666666; }')
-
- self.info_show_downloads = QtWidgets.QToolButton()
- self.info_show_downloads.setIcon(QtGui.QIcon(self.common.get_resource_path('images/download_window_gray.png')))
- self.info_show_downloads.setCheckable(True)
- self.info_show_downloads.toggled.connect(self.downloads_toggled)
- self.info_show_downloads.setToolTip(strings._('gui_downloads_window_tooltip', True))
-
- self.info_in_progress_downloads_count = QtWidgets.QLabel()
- self.info_in_progress_downloads_count.setStyleSheet('QLabel { font-size: 12px; color: #666666; }')
-
- self.info_completed_downloads_count = QtWidgets.QLabel()
- self.info_completed_downloads_count.setStyleSheet('QLabel { font-size: 12px; color: #666666; }')
-
- self.update_downloads_completed(self.downloads_in_progress)
- self.update_downloads_in_progress(self.downloads_in_progress)
-
- self.info_layout.addWidget(self.info_label)
- self.info_layout.addStretch()
- self.info_layout.addWidget(self.info_in_progress_downloads_count)
- self.info_layout.addWidget(self.info_completed_downloads_count)
- self.info_layout.addWidget(self.info_show_downloads)
-
- self.info_widget = QtWidgets.QWidget()
- self.info_widget.setLayout(self.info_layout)
- self.info_widget.hide()
-
- # Server status indicator on the status bar
- self.server_status_image_stopped = QtGui.QImage(self.common.get_resource_path('images/server_stopped.png'))
- self.server_status_image_working = QtGui.QImage(self.common.get_resource_path('images/server_working.png'))
- self.server_status_image_started = QtGui.QImage(self.common.get_resource_path('images/server_started.png'))
- self.server_status_image_label = QtWidgets.QLabel()
- self.server_status_image_label.setFixedWidth(20)
- self.server_status_label = QtWidgets.QLabel()
- self.server_status_label.setStyleSheet('QLabel { font-style: italic; color: #666666; }')
- server_status_indicator_layout = QtWidgets.QHBoxLayout()
- server_status_indicator_layout.addWidget(self.server_status_image_label)
- server_status_indicator_layout.addWidget(self.server_status_label)
- self.server_status_indicator = QtWidgets.QWidget()
- self.server_status_indicator.setLayout(server_status_indicator_layout)
- self.update_server_status_indicator()
-
# Status bar
self.status_bar = QtWidgets.QStatusBar()
self.status_bar.setSizeGripEnabled(False)
@@ -236,24 +147,11 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.server_share_status_label.setStyleSheet('QLabel { font-style: italic; color: #666666; padding: 2px; }')
self.status_bar.insertWidget(0, self.server_share_status_label)
- # Primary action layout
- primary_action_layout = QtWidgets.QVBoxLayout()
- primary_action_layout.addWidget(self.server_status)
- primary_action_layout.addWidget(self.filesize_warning)
- self.primary_action = QtWidgets.QWidget()
- self.primary_action.setLayout(primary_action_layout)
- self.primary_action.hide()
- self.update_primary_action()
-
# Layouts
contents_layout = QtWidgets.QVBoxLayout()
contents_layout.setContentsMargins(10, 10, 10, 10)
contents_layout.addWidget(self.receive_mode)
contents_layout.addWidget(self.share_mode)
- # TODO: move these into ShareMode
- contents_layout.addWidget(self.info_widget)
- contents_layout.addLayout(self.file_selection)
- contents_layout.addWidget(self.primary_action)
layout = QtWidgets.QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
@@ -265,9 +163,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.setCentralWidget(central_widget)
self.show()
- # Always start with focus on file selection
- self.file_selection.setFocus()
-
# The server isn't active yet
self.set_server_active(False)
@@ -314,46 +209,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.mode = self.MODE_RECEIVE
self.update_mode_switcher()
- def update_primary_action(self):
- # Show or hide primary action layout
- file_count = self.file_selection.file_list.count()
- if file_count > 0:
- self.primary_action.show()
- self.info_widget.show()
-
- # Update the file count in the info label
- total_size_bytes = 0
- for index in range(self.file_selection.file_list.count()):
- item = self.file_selection.file_list.item(index)
- total_size_bytes += item.size_bytes
- total_size_readable = self.common.human_readable_filesize(total_size_bytes)
-
- if file_count > 1:
- self.info_label.setText(strings._('gui_file_info', True).format(file_count, total_size_readable))
- else:
- self.info_label.setText(strings._('gui_file_info_single', True).format(file_count, total_size_readable))
-
- else:
- self.primary_action.hide()
- self.info_widget.hide()
-
- # Resize window
- self.adjustSize()
-
- def update_server_status_indicator(self):
- self.common.log('OnionShareGui', 'update_server_status_indicator')
-
- # Set the status image
- if self.server_status.status == self.server_status.STATUS_STOPPED:
- self.server_status_image_label.setPixmap(QtGui.QPixmap.fromImage(self.server_status_image_stopped))
- self.server_status_label.setText(strings._('gui_status_indicator_stopped', True))
- elif self.server_status.status == self.server_status.STATUS_WORKING:
- self.server_status_image_label.setPixmap(QtGui.QPixmap.fromImage(self.server_status_image_working))
- self.server_status_label.setText(strings._('gui_status_indicator_working', True))
- elif self.server_status.status == self.server_status.STATUS_STARTED:
- self.server_status_image_label.setPixmap(QtGui.QPixmap.fromImage(self.server_status_image_started))
- self.server_status_label.setText(strings._('gui_status_indicator_started', True))
-
def _initSystemTray(self):
menu = QtWidgets.QMenu()
self.settingsAction = menu.addAction(strings._('gui_settings_window_title', True))
@@ -445,165 +300,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
# When settings close, refresh the server status UI
self.server_status.update()
- def start_server(self):
- """
- Start the onionshare server. This uses multiple threads to start the Tor onion
- server and the web app.
- """
- self.common.log('OnionShareGui', 'start_server')
-
- self.set_server_active(True)
-
- self.app.set_stealth(self.common.settings.get('use_stealth'))
-
- # Hide and reset the downloads if we have previously shared
- self.downloads.reset_downloads()
- self.reset_info_counters()
- self.status_bar.clearMessage()
- self.server_share_status_label.setText('')
-
- # Reset web counters
- self.web.download_count = 0
- self.web.error404_count = 0
-
- # start the onion service in a new thread
- def start_onion_service(self):
- try:
- self.app.start_onion_service()
- self.starting_server_step2.emit()
-
- except (TorTooOld, TorErrorInvalidSetting, TorErrorAutomatic, TorErrorSocketPort, TorErrorSocketFile, TorErrorMissingPassword, TorErrorUnreadableCookieFile, TorErrorAuthError, TorErrorProtocolError, BundledTorTimeout, OSError) as e:
- self.starting_server_error.emit(e.args[0])
- return
-
-
- self.app.stay_open = not self.common.settings.get('close_after_first_download')
-
- # start onionshare http service in new thread
- t = threading.Thread(target=self.web.start, args=(self.app.port, self.app.stay_open, self.common.settings.get('slug')))
- t.daemon = True
- t.start()
- # wait for modules in thread to load, preventing a thread-related cx_Freeze crash
- time.sleep(0.2)
-
- self.common.log('OnionshareGui', 'start_server', 'Starting an onion thread')
- self.t = OnionThread(self.common, function=start_onion_service, kwargs={'self': self})
- self.t.daemon = True
- self.t.start()
-
- def start_server_step2(self):
- """
- Step 2 in starting the onionshare server. Zipping up files.
- """
- self.common.log('OnionShareGui', 'start_server_step2')
-
- # add progress bar to the status bar, indicating the compressing of files.
- self._zip_progress_bar = ZipProgressBar(0)
- self.filenames = []
- for index in range(self.file_selection.file_list.count()):
- self.filenames.append(self.file_selection.file_list.item(index).filename)
-
- self._zip_progress_bar.total_files_size = OnionShareGui._compute_total_size(self.filenames)
- self.status_bar.insertWidget(0, self._zip_progress_bar)
-
- # prepare the files for sending in a new thread
- def finish_starting_server(self):
- # prepare files to share
- def _set_processed_size(x):
- if self._zip_progress_bar != None:
- self._zip_progress_bar.update_processed_size_signal.emit(x)
- try:
- self.web.set_file_info(self.filenames, processed_size_callback=_set_processed_size)
- self.app.cleanup_filenames.append(self.web.zip_filename)
- self.starting_server_step3.emit()
-
- # done
- self.start_server_finished.emit()
- except OSError as e:
- self.starting_server_error.emit(e.strerror)
- return
-
- t = threading.Thread(target=finish_starting_server, kwargs={'self': self})
- t.daemon = True
- t.start()
-
- def start_server_step3(self):
- """
- Step 3 in starting the onionshare server. This displays the large filesize
- warning, if applicable.
- """
- self.common.log('OnionShareGui', 'start_server_step3')
-
- # Remove zip progress bar
- if self._zip_progress_bar is not None:
- self.status_bar.removeWidget(self._zip_progress_bar)
- self._zip_progress_bar = None
-
- # warn about sending large files over Tor
- if self.web.zip_filesize >= 157286400: # 150mb
- self.filesize_warning.setText(strings._("large_filesize", True))
- self.filesize_warning.show()
-
- if self.common.settings.get('shutdown_timeout'):
- # Convert the date value to seconds between now and then
- now = QtCore.QDateTime.currentDateTime()
- self.timeout = now.secsTo(self.server_status.timeout)
- # Set the shutdown timeout value
- if self.timeout > 0:
- self.app.shutdown_timer = ShutdownTimer(self.common, self.timeout)
- 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):
- """
- If there's an error when trying to start the onion service
- """
- self.common.log('OnionShareGui', 'start_server_error')
-
- self.set_server_active(False)
-
- Alert(self.common, error, QtWidgets.QMessageBox.Warning)
- self.server_status.stop_server()
- if self._zip_progress_bar is not None:
- self.status_bar.removeWidget(self._zip_progress_bar)
- self._zip_progress_bar = None
- self.status_bar.clearMessage()
-
- def cancel_server(self):
- """
- Cancel the server while it is preparing to start
- """
- if self.t:
- self.t.quit()
- self.stop_server()
-
- def stop_server(self):
- """
- Stop the onionshare server.
- """
- self.common.log('OnionShareGui', 'stop_server')
-
- if self.server_status.status != self.server_status.STATUS_STOPPED:
- try:
- self.web.stop(self.app.port)
- except:
- # Probably we had no port to begin with (Onion service didn't start)
- pass
- self.app.cleanup()
- # Remove ephemeral service, but don't disconnect from Tor
- self.onion.cleanup(stop_tor=False)
- self.filesize_warning.hide()
- self.downloads_in_progress = 0
- self.downloads_completed = 0
- self.update_downloads_in_progress(0)
- self.file_selection.file_list.adjustSize()
-
- self.set_server_active(False)
- self.stop_server_finished.emit()
-
def check_for_updates(self):
"""
Check for updates in a new thread, if enabled.
@@ -617,16 +313,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.update_thread.update_available.connect(update_available)
self.update_thread.start()
- @staticmethod
- def _compute_total_size(filenames):
- total_size = 0
- for filename in filenames:
- if os.path.isfile(filename):
- total_size += os.path.getsize(filename)
- if os.path.isdir(filename):
- total_size += Common.dir_size(filename)
- return total_size
-
def check_for_requests(self):
"""
Check for messages communicated from the web app, and update the GUI accordingly.
@@ -733,16 +419,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.status_bar.clearMessage()
self.server_share_status_label.setText(strings._('timeout_download_still_running', True))
- def downloads_toggled(self, checked):
- """
- When the 'Show/hide downloads' button is toggled, show or hide the downloads window.
- """
- self.common.log('OnionShareGui', 'toggle_downloads')
- if checked:
- self.downloads.downloads_container.show()
- else:
- self.downloads.downloads_container.hide()
-
def copy_url(self):
"""
When the URL gets copied to the clipboard, display this in the status bar.
@@ -777,39 +453,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
# Disable settings menu action when server is active
self.settingsAction.setEnabled(not active)
- def reset_info_counters(self):
- """
- Set the info counters back to zero.
- """
- self.update_downloads_completed(0)
- self.update_downloads_in_progress(0)
- self.info_show_downloads.setIcon(QtGui.QIcon(self.common.get_resource_path('images/download_window_gray.png')))
- self.downloads.no_downloads_label.show()
- self.downloads.downloads_container.resize(self.downloads.downloads_container.sizeHint())
-
- def update_downloads_completed(self, count):
- """
- Update the 'Downloads completed' info widget.
- """
- if count == 0:
- self.info_completed_downloads_image = self.common.get_resource_path('images/download_completed_none.png')
- else:
- self.info_completed_downloads_image = self.common.get_resource_path('images/download_completed.png')
- self.info_completed_downloads_count.setText(' {1:d}'.format(self.info_completed_downloads_image, count))
- self.info_completed_downloads_count.setToolTip(strings._('info_completed_downloads_tooltip', True).format(count))
-
- def update_downloads_in_progress(self, count):
- """
- Update the 'Downloads in progress' info widget.
- """
- if count == 0:
- self.info_in_progress_downloads_image = self.common.get_resource_path('images/download_in_progress_none.png')
- else:
- self.info_in_progress_downloads_image = self.common.get_resource_path('images/download_in_progress.png')
- self.info_show_downloads.setIcon(QtGui.QIcon(self.common.get_resource_path('images/download_window_green.png')))
- self.info_in_progress_downloads_count.setText(' {1:d}'.format(self.info_in_progress_downloads_image, count))
- self.info_in_progress_downloads_count.setToolTip(strings._('info_in_progress_downloads_tooltip', True).format(count))
-
def closeEvent(self, e):
self.common.log('OnionShareGui', 'closeEvent')
try:
diff --git a/onionshare_gui/share_mode.py b/onionshare_gui/share_mode.py
index 81dd62d5..b6aa02c9 100644
--- a/onionshare_gui/share_mode.py
+++ b/onionshare_gui/share_mode.py
@@ -20,6 +20,7 @@ along with this program. If not, see .
from PyQt5 import QtCore, QtWidgets, QtGui
from onionshare import strings
+from .mode import Mode
class ShareMode(QtWidgets.QWidget):
"""
@@ -28,3 +29,363 @@ class ShareMode(QtWidgets.QWidget):
def __init__(self, common):
super(ShareMode, self).__init__()
self.common = common
+
+ # File selection
+ self.file_selection = FileSelection(self.common)
+ if filenames:
+ for filename in filenames:
+ self.file_selection.file_list.add_file(filename)
+
+ # Server status
+ self.server_status = ServerStatus(self.common, self.qtapp, self.app, self.web, self.file_selection)
+ self.server_status.server_started.connect(self.file_selection.server_started)
+ self.server_status.server_started.connect(self.start_server)
+ self.server_status.server_started.connect(self.update_server_status_indicator)
+ self.server_status.server_stopped.connect(self.file_selection.server_stopped)
+ self.server_status.server_stopped.connect(self.stop_server)
+ self.server_status.server_stopped.connect(self.update_server_status_indicator)
+ self.server_status.server_stopped.connect(self.update_primary_action)
+ self.server_status.server_canceled.connect(self.cancel_server)
+ self.server_status.server_canceled.connect(self.file_selection.server_stopped)
+ self.server_status.server_canceled.connect(self.update_primary_action)
+ self.start_server_finished.connect(self.clear_message)
+ self.start_server_finished.connect(self.server_status.start_server_finished)
+ self.start_server_finished.connect(self.update_server_status_indicator)
+ self.stop_server_finished.connect(self.server_status.stop_server_finished)
+ self.stop_server_finished.connect(self.update_server_status_indicator)
+ self.file_selection.file_list.files_updated.connect(self.server_status.update)
+ self.file_selection.file_list.files_updated.connect(self.update_primary_action)
+ self.server_status.url_copied.connect(self.copy_url)
+ self.server_status.hidservauth_copied.connect(self.copy_hidservauth)
+ self.starting_server_step2.connect(self.start_server_step2)
+ self.starting_server_step3.connect(self.start_server_step3)
+ self.starting_server_error.connect(self.start_server_error)
+ self.server_status.button_clicked.connect(self.clear_message)
+
+ # Filesize warning
+ self.filesize_warning = QtWidgets.QLabel()
+ self.filesize_warning.setWordWrap(True)
+ self.filesize_warning.setStyleSheet('padding: 10px 0; font-weight: bold; color: #333333;')
+ self.filesize_warning.hide()
+
+ # Downloads
+ self.downloads = Downloads(self.common)
+ self.new_download = False
+ self.downloads_in_progress = 0
+ self.downloads_completed = 0
+
+ # Info label along top of screen
+ self.info_layout = QtWidgets.QHBoxLayout()
+ self.info_label = QtWidgets.QLabel()
+ self.info_label.setStyleSheet('QLabel { font-size: 12px; color: #666666; }')
+
+ self.info_show_downloads = QtWidgets.QToolButton()
+ self.info_show_downloads.setIcon(QtGui.QIcon(self.common.get_resource_path('images/download_window_gray.png')))
+ self.info_show_downloads.setCheckable(True)
+ self.info_show_downloads.toggled.connect(self.downloads_toggled)
+ self.info_show_downloads.setToolTip(strings._('gui_downloads_window_tooltip', True))
+
+ self.info_in_progress_downloads_count = QtWidgets.QLabel()
+ self.info_in_progress_downloads_count.setStyleSheet('QLabel { font-size: 12px; color: #666666; }')
+
+ self.info_completed_downloads_count = QtWidgets.QLabel()
+ self.info_completed_downloads_count.setStyleSheet('QLabel { font-size: 12px; color: #666666; }')
+
+ self.update_downloads_completed(self.downloads_in_progress)
+ self.update_downloads_in_progress(self.downloads_in_progress)
+
+ self.info_layout.addWidget(self.info_label)
+ self.info_layout.addStretch()
+ self.info_layout.addWidget(self.info_in_progress_downloads_count)
+ self.info_layout.addWidget(self.info_completed_downloads_count)
+ self.info_layout.addWidget(self.info_show_downloads)
+
+ self.info_widget = QtWidgets.QWidget()
+ self.info_widget.setLayout(self.info_layout)
+ self.info_widget.hide()
+
+ # Server status indicator on the status bar
+ self.server_status_image_stopped = QtGui.QImage(self.common.get_resource_path('images/server_stopped.png'))
+ self.server_status_image_working = QtGui.QImage(self.common.get_resource_path('images/server_working.png'))
+ self.server_status_image_started = QtGui.QImage(self.common.get_resource_path('images/server_started.png'))
+ self.server_status_image_label = QtWidgets.QLabel()
+ self.server_status_image_label.setFixedWidth(20)
+ self.server_status_label = QtWidgets.QLabel()
+ self.server_status_label.setStyleSheet('QLabel { font-style: italic; color: #666666; }')
+ server_status_indicator_layout = QtWidgets.QHBoxLayout()
+ server_status_indicator_layout.addWidget(self.server_status_image_label)
+ server_status_indicator_layout.addWidget(self.server_status_label)
+ self.server_status_indicator = QtWidgets.QWidget()
+ self.server_status_indicator.setLayout(server_status_indicator_layout)
+ self.update_server_status_indicator()
+
+ # Primary action layout
+ primary_action_layout = QtWidgets.QVBoxLayout()
+ primary_action_layout.addWidget(self.server_status)
+ primary_action_layout.addWidget(self.filesize_warning)
+ self.primary_action = QtWidgets.QWidget()
+ self.primary_action.setLayout(primary_action_layout)
+ self.primary_action.hide()
+ self.update_primary_action()
+
+ # Layout
+ layout = QtWidgets.QVBoxLayout()
+ layout.addWidget(self.info_widget)
+ layout.addLayout(self.file_selection)
+ layout.addWidget(self.primary_action)
+ self.setLayout(layout)
+
+ # Always start with focus on file selection
+ self.file_selection.setFocus()
+
+ def update_primary_action(self):
+ # Show or hide primary action layout
+ file_count = self.file_selection.file_list.count()
+ if file_count > 0:
+ self.primary_action.show()
+ self.info_widget.show()
+
+ # Update the file count in the info label
+ total_size_bytes = 0
+ for index in range(self.file_selection.file_list.count()):
+ item = self.file_selection.file_list.item(index)
+ total_size_bytes += item.size_bytes
+ total_size_readable = self.common.human_readable_filesize(total_size_bytes)
+
+ if file_count > 1:
+ self.info_label.setText(strings._('gui_file_info', True).format(file_count, total_size_readable))
+ else:
+ self.info_label.setText(strings._('gui_file_info_single', True).format(file_count, total_size_readable))
+
+ else:
+ self.primary_action.hide()
+ self.info_widget.hide()
+
+ # Resize window
+ self.adjustSize()
+
+ def update_server_status_indicator(self):
+ self.common.log('OnionShareGui', 'update_server_status_indicator')
+
+ # Set the status image
+ if self.server_status.status == self.server_status.STATUS_STOPPED:
+ self.server_status_image_label.setPixmap(QtGui.QPixmap.fromImage(self.server_status_image_stopped))
+ self.server_status_label.setText(strings._('gui_status_indicator_stopped', True))
+ elif self.server_status.status == self.server_status.STATUS_WORKING:
+ self.server_status_image_label.setPixmap(QtGui.QPixmap.fromImage(self.server_status_image_working))
+ self.server_status_label.setText(strings._('gui_status_indicator_working', True))
+ elif self.server_status.status == self.server_status.STATUS_STARTED:
+ self.server_status_image_label.setPixmap(QtGui.QPixmap.fromImage(self.server_status_image_started))
+ self.server_status_label.setText(strings._('gui_status_indicator_started', True))
+
+ def start_server(self):
+ """
+ Start the onionshare server. This uses multiple threads to start the Tor onion
+ server and the web app.
+ """
+ self.common.log('OnionShareGui', 'start_server')
+
+ self.set_server_active(True)
+
+ self.app.set_stealth(self.common.settings.get('use_stealth'))
+
+ # Hide and reset the downloads if we have previously shared
+ self.downloads.reset_downloads()
+ self.reset_info_counters()
+ self.status_bar.clearMessage()
+ self.server_share_status_label.setText('')
+
+ # Reset web counters
+ self.web.download_count = 0
+ self.web.error404_count = 0
+
+ # start the onion service in a new thread
+ def start_onion_service(self):
+ try:
+ self.app.start_onion_service()
+ self.starting_server_step2.emit()
+
+ except (TorTooOld, TorErrorInvalidSetting, TorErrorAutomatic, TorErrorSocketPort, TorErrorSocketFile, TorErrorMissingPassword, TorErrorUnreadableCookieFile, TorErrorAuthError, TorErrorProtocolError, BundledTorTimeout, OSError) as e:
+ self.starting_server_error.emit(e.args[0])
+ return
+
+
+ self.app.stay_open = not self.common.settings.get('close_after_first_download')
+
+ # start onionshare http service in new thread
+ t = threading.Thread(target=self.web.start, args=(self.app.port, self.app.stay_open, self.common.settings.get('slug')))
+ t.daemon = True
+ t.start()
+ # wait for modules in thread to load, preventing a thread-related cx_Freeze crash
+ time.sleep(0.2)
+
+ self.common.log('OnionshareGui', 'start_server', 'Starting an onion thread')
+ self.t = OnionThread(self.common, function=start_onion_service, kwargs={'self': self})
+ self.t.daemon = True
+ self.t.start()
+
+ def start_server_step2(self):
+ """
+ Step 2 in starting the onionshare server. Zipping up files.
+ """
+ self.common.log('OnionShareGui', 'start_server_step2')
+
+ # add progress bar to the status bar, indicating the compressing of files.
+ self._zip_progress_bar = ZipProgressBar(0)
+ self.filenames = []
+ for index in range(self.file_selection.file_list.count()):
+ self.filenames.append(self.file_selection.file_list.item(index).filename)
+
+ self._zip_progress_bar.total_files_size = ShareMode._compute_total_size(self.filenames)
+ self.status_bar.insertWidget(0, self._zip_progress_bar)
+
+ # prepare the files for sending in a new thread
+ def finish_starting_server(self):
+ # prepare files to share
+ def _set_processed_size(x):
+ if self._zip_progress_bar != None:
+ self._zip_progress_bar.update_processed_size_signal.emit(x)
+ try:
+ self.web.set_file_info(self.filenames, processed_size_callback=_set_processed_size)
+ self.app.cleanup_filenames.append(self.web.zip_filename)
+ self.starting_server_step3.emit()
+
+ # done
+ self.start_server_finished.emit()
+ except OSError as e:
+ self.starting_server_error.emit(e.strerror)
+ return
+
+ t = threading.Thread(target=finish_starting_server, kwargs={'self': self})
+ t.daemon = True
+ t.start()
+
+ def start_server_step3(self):
+ """
+ Step 3 in starting the onionshare server. This displays the large filesize
+ warning, if applicable.
+ """
+ self.common.log('OnionShareGui', 'start_server_step3')
+
+ # Remove zip progress bar
+ if self._zip_progress_bar is not None:
+ self.status_bar.removeWidget(self._zip_progress_bar)
+ self._zip_progress_bar = None
+
+ # warn about sending large files over Tor
+ if self.web.zip_filesize >= 157286400: # 150mb
+ self.filesize_warning.setText(strings._("large_filesize", True))
+ self.filesize_warning.show()
+
+ if self.common.settings.get('shutdown_timeout'):
+ # Convert the date value to seconds between now and then
+ now = QtCore.QDateTime.currentDateTime()
+ self.timeout = now.secsTo(self.server_status.timeout)
+ # Set the shutdown timeout value
+ if self.timeout > 0:
+ self.app.shutdown_timer = ShutdownTimer(self.common, self.timeout)
+ 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):
+ """
+ If there's an error when trying to start the onion service
+ """
+ self.common.log('OnionShareGui', 'start_server_error')
+
+ self.set_server_active(False)
+
+ Alert(self.common, error, QtWidgets.QMessageBox.Warning)
+ self.server_status.stop_server()
+ if self._zip_progress_bar is not None:
+ self.status_bar.removeWidget(self._zip_progress_bar)
+ self._zip_progress_bar = None
+ self.status_bar.clearMessage()
+
+ def cancel_server(self):
+ """
+ Cancel the server while it is preparing to start
+ """
+ if self.t:
+ self.t.quit()
+ self.stop_server()
+
+ def stop_server(self):
+ """
+ Stop the onionshare server.
+ """
+ self.common.log('OnionShareGui', 'stop_server')
+
+ if self.server_status.status != self.server_status.STATUS_STOPPED:
+ try:
+ self.web.stop(self.app.port)
+ except:
+ # Probably we had no port to begin with (Onion service didn't start)
+ pass
+ self.app.cleanup()
+ # Remove ephemeral service, but don't disconnect from Tor
+ self.onion.cleanup(stop_tor=False)
+ self.filesize_warning.hide()
+ self.downloads_in_progress = 0
+ self.downloads_completed = 0
+ self.update_downloads_in_progress(0)
+ self.file_selection.file_list.adjustSize()
+
+ self.set_server_active(False)
+ self.stop_server_finished.emit()
+
+ def downloads_toggled(self, checked):
+ """
+ When the 'Show/hide downloads' button is toggled, show or hide the downloads window.
+ """
+ self.common.log('OnionShareGui', 'toggle_downloads')
+ if checked:
+ self.downloads.downloads_container.show()
+ else:
+ self.downloads.downloads_container.hide()
+
+ def reset_info_counters(self):
+ """
+ Set the info counters back to zero.
+ """
+ self.update_downloads_completed(0)
+ self.update_downloads_in_progress(0)
+ self.info_show_downloads.setIcon(QtGui.QIcon(self.common.get_resource_path('images/download_window_gray.png')))
+ self.downloads.no_downloads_label.show()
+ self.downloads.downloads_container.resize(self.downloads.downloads_container.sizeHint())
+
+ def update_downloads_completed(self, count):
+ """
+ Update the 'Downloads completed' info widget.
+ """
+ if count == 0:
+ self.info_completed_downloads_image = self.common.get_resource_path('images/download_completed_none.png')
+ else:
+ self.info_completed_downloads_image = self.common.get_resource_path('images/download_completed.png')
+ self.info_completed_downloads_count.setText(' {1:d}'.format(self.info_completed_downloads_image, count))
+ self.info_completed_downloads_count.setToolTip(strings._('info_completed_downloads_tooltip', True).format(count))
+
+ def update_downloads_in_progress(self, count):
+ """
+ Update the 'Downloads in progress' info widget.
+ """
+ if count == 0:
+ self.info_in_progress_downloads_image = self.common.get_resource_path('images/download_in_progress_none.png')
+ else:
+ self.info_in_progress_downloads_image = self.common.get_resource_path('images/download_in_progress.png')
+ self.info_show_downloads.setIcon(QtGui.QIcon(self.common.get_resource_path('images/download_window_green.png')))
+ self.info_in_progress_downloads_count.setText(' {1:d}'.format(self.info_in_progress_downloads_image, count))
+ self.info_in_progress_downloads_count.setToolTip(strings._('info_in_progress_downloads_tooltip', True).format(count))
+
+ @staticmethod
+ def _compute_total_size(filenames):
+ total_size = 0
+ for filename in filenames:
+ if os.path.isfile(filename):
+ total_size += os.path.getsize(filename)
+ if os.path.isdir(filename):
+ total_size += Common.dir_size(filename)
+ return total_size