Merge branch 'develop' into receiver-mode

This commit is contained in:
Micah Lee 2018-04-22 17:38:28 -07:00
commit 8c89a05fd9
No known key found for this signature in database
GPG Key ID: 403C2657CD994F73
9 changed files with 139 additions and 83 deletions

View File

@ -207,6 +207,8 @@ Section "install"
File "${BINPATH}\share\images\download_completed_none.png"
File "${BINPATH}\share\images\download_in_progress.png"
File "${BINPATH}\share\images\download_in_progress_none.png"
File "${BINPATH}\share\images\download_window_gray.png"
File "${BINPATH}\share\images\download_window_green.png"
File "${BINPATH}\share\images\favicon.ico"
File "${BINPATH}\share\images\file_delete.png"
File "${BINPATH}\share\images\info.png"
@ -393,6 +395,8 @@ FunctionEnd
Delete "$INSTDIR\share\images\download_completed_none.png"
Delete "$INSTDIR\share\images\download_in_progress.png"
Delete "$INSTDIR\share\images\download_in_progress_none.png"
Delete "$INSTDIR\share\images\download_window_gray.png"
Delete "$INSTDIR\share\images\download_window_green.png"
Delete "$INSTDIR\share\images\favicon.ico"
Delete "$INSTDIR\share\images\file_delete.png"
Delete "$INSTDIR\share\images\info.png"

View File

@ -110,8 +110,7 @@ def main():
app = OnionShare(common, onion, local_only, stay_open, shutdown_timeout)
# Launch the gui
web.stay_open = stay_open
gui = OnionShareGui(common, web, onion, qtapp, app, filenames, config)
gui = OnionShareGui(onion, qtapp, app, filenames, config, local_only)
# Clean up when app quits
def shutdown():

View File

@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import time
from PyQt5 import QtCore, QtWidgets
from PyQt5 import QtCore, QtWidgets, QtGui
from onionshare import strings
@ -103,19 +103,39 @@ class Downloads(QtWidgets.QWidget):
self.common = common
self.downloads = {}
self.downloads_container = QtWidgets.QScrollArea()
self.downloads_container.setWidget(self)
self.downloads_container.setWindowTitle(strings._('gui_downloads', True))
self.downloads_container.setWidgetResizable(True)
self.downloads_container.setMaximumHeight(600)
self.downloads_container.setMinimumHeight(150)
self.downloads_container.setMinimumWidth(350)
self.downloads_container.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png')))
self.downloads_container.setWindowFlags(QtCore.Qt.Sheet | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.CustomizeWindowHint)
self.downloads_container.vbar = self.downloads_container.verticalScrollBar()
self.downloads_label = QtWidgets.QLabel(strings._('gui_downloads', True))
self.downloads_label.setStyleSheet('QLabel { font-weight: bold; font-size 14px; text-align: center; }')
self.no_downloads_label = QtWidgets.QLabel(strings._('gui_no_downloads', True))
self.downloads_layout = QtWidgets.QVBoxLayout()
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.downloads_label)
self.layout.addWidget(self.no_downloads_label)
self.layout.addLayout(self.downloads_layout)
self.layout.addStretch()
self.setLayout(self.layout)
def add_download(self, download_id, total_bytes):
"""
Add a new download progress bar.
"""
self.parent().show()
# add it to the list
download = Download(self.common, download_id, total_bytes)
self.downloads[download_id] = download
self.layout.insertWidget(-1, download.progress_bar)
self.downloads_layout.addWidget(download.progress_bar)
def update_download(self, download_id, downloaded_bytes):
"""
@ -134,6 +154,6 @@ class Downloads(QtWidgets.QWidget):
Reset the downloads back to zero
"""
for download in self.downloads.values():
self.layout.removeWidget(download.progress_bar)
self.downloads_layout.removeWidget(download.progress_bar)
download.progress_bar.close()
self.downloads = {}

View File

@ -46,7 +46,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
starting_server_step3 = QtCore.pyqtSignal()
starting_server_error = QtCore.pyqtSignal(str)
def __init__(self, common, web, onion, qtapp, app, filenames, config=False):
def __init__(self, common, web, onion, qtapp, app, filenames, config=False, local_only=False):
super(OnionShareGui, self).__init__()
self.common = common
@ -58,6 +58,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.onion = onion
self.qtapp = qtapp
self.app = app
self.local_only = local_only
self.setWindowTitle('OnionShare')
self.setWindowIcon(QtGui.QIcon(self.common.get_resource_path('images/logo.png')))
@ -106,14 +107,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.filesize_warning.hide()
# Downloads
self.downloads = Downloads(self.common)
self.downloads_container = QtWidgets.QScrollArea()
self.downloads_container.setWidget(self.downloads)
self.downloads_container.setWidgetResizable(True)
self.downloads_container.setMaximumHeight(200)
self.downloads_container.setMinimumHeight(75)
self.vbar = self.downloads_container.verticalScrollBar()
self.downloads_container.hide() # downloads start out hidden
self.downloads = Downloads()
self.new_download = False
self.downloads_in_progress = 0
self.downloads_completed = 0
@ -123,6 +117,12 @@ class OnionShareGui(QtWidgets.QMainWindow):
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(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; }')
@ -136,6 +136,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
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)
@ -193,7 +194,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
primary_action_layout = QtWidgets.QVBoxLayout()
primary_action_layout.addWidget(self.server_status)
primary_action_layout.addWidget(self.filesize_warning)
primary_action_layout.addWidget(self.downloads_container)
self.primary_action = QtWidgets.QWidget()
self.primary_action.setLayout(primary_action_layout)
self.primary_action.hide()
@ -223,7 +223,8 @@ class OnionShareGui(QtWidgets.QMainWindow):
tor_con = TorConnectionDialog(self.common, self.qtapp, self.onion)
tor_con.canceled.connect(self._tor_connection_canceled)
tor_con.open_settings.connect(self._tor_connection_open_settings)
tor_con.start()
if not self.local_only:
tor_con.start()
# Start the timer
self.timer.start(500)
@ -341,19 +342,21 @@ class OnionShareGui(QtWidgets.QMainWindow):
# 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()
if not self.local_only:
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.primary_action.show()
self.info_widget.show()
self.status_bar.clearMessage()
# If we switched off the shutdown timeout setting, ensure the widget is hidden.
if not self.common.settings.get('shutdown_timeout'):
self.server_status.shutdown_timeout_container.hide()
d = SettingsDialog(self.common, self.onion, self.qtapp, self.config)
d = SettingsDialog(self.common, self.onion, self.qtapp, self.config, self.local_only)
d.settings_saved.connect(reload_settings)
d.exec_()
@ -372,7 +375,6 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.app.set_stealth(self.common.settings.get('use_stealth'))
# Hide and reset the downloads if we have previously shared
self.downloads_container.hide()
self.downloads.reset_downloads()
self.reset_info_counters()
self.status_bar.clearMessage()
@ -413,7 +415,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
"""
self.common.log('OnionShareGui', 'start_server_step2')
# add progress bar to the status bar, indicating the crunching of files.
# 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()):
@ -549,20 +551,22 @@ 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.common.settings.get('systray_notifications'):
self.systemTray.showMessage(strings._('gui_tor_connection_lost', True), strings._('gui_tor_connection_error_settings', True))
if not self.local_only:
# 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.primary_action.hide()
self.info_widget.hide()
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:
self.vbar.setValue(self.vbar.maximum())
self.downloads.downloads_container.vbar.setValue(self.downloads.downloads_container.vbar.maximum())
self.new_download = False
events = []
@ -580,8 +584,8 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.status_bar.showMessage(strings._('download_page_loaded', True))
elif event["type"] == self.web.REQUEST_DOWNLOAD:
self.downloads_container.show() # show the downloads layout
self.downloads.add_download(event["data"]["id"], self.web.zip_filesize)
self.downloads.no_downloads_label.hide()
self.downloads.add_download(event["data"]["id"], web.zip_filesize)
self.new_download = True
self.downloads_in_progress += 1
self.update_downloads_in_progress(self.downloads_in_progress)
@ -647,6 +651,16 @@ 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.
"""
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.
@ -687,6 +701,9 @@ class OnionShareGui(QtWidgets.QMainWindow):
"""
self.update_downloads_completed(0)
self.update_downloads_in_progress(0)
self.info_show_downloads.setIcon(QtGui.QIcon(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):
"""
@ -707,6 +724,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
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('<img src="{0:s}" /> {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))

View File

@ -34,7 +34,7 @@ class SettingsDialog(QtWidgets.QDialog):
"""
settings_saved = QtCore.pyqtSignal()
def __init__(self, common, onion, qtapp, config=False):
def __init__(self, common, onion, qtapp, config=False, local_only=False):
super(SettingsDialog, self).__init__()
self.common = common
@ -44,6 +44,7 @@ class SettingsDialog(QtWidgets.QDialog):
self.onion = onion
self.qtapp = qtapp
self.config = config
self.local_only = local_only
self.setModal(True)
self.setWindowTitle(strings._('gui_settings_window_title', True))
@ -499,6 +500,9 @@ class SettingsDialog(QtWidgets.QDialog):
"""
if checked:
self.tor_bridges_use_custom_textbox_options.hide()
# Alert the user about meek's costliness if it looks like they're turning it on
if not self.old_settings.get('tor_bridges_use_meek_lite_amazon'):
Alert(strings._('gui_settings_meek_lite_expensive_warning', True), QtWidgets.QMessageBox.Warning)
def tor_bridges_use_meek_lite_azure_radio_toggled(self, checked):
"""
@ -506,6 +510,9 @@ class SettingsDialog(QtWidgets.QDialog):
"""
if checked:
self.tor_bridges_use_custom_textbox_options.hide()
# Alert the user about meek's costliness if it looks like they're turning it on
if not self.old_settings.get('tor_bridges_use_meek_lite_azure'):
Alert(strings._('gui_settings_meek_lite_expensive_warning', True), QtWidgets.QMessageBox.Warning)
def tor_bridges_use_custom_radio_toggled(self, checked):
"""
@ -674,48 +681,52 @@ 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.is_authenticated():
self.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
have changed for the given keys.
"""
for key in keys:
if s1.get(key) != s2.get(key):
return True
return False
if not self.local_only:
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
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',
'no_bridges', 'tor_bridges_use_obfs4',
'tor_bridges_use_meek_lite_amazon', 'tor_bridges_use_meek_lite_azure',
'tor_bridges_use_custom_bridges']):
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',
'no_bridges', 'tor_bridges_use_obfs4',
'tor_bridges_use_meek_lite_amazon', 'tor_bridges_use_meek_lite_azure',
'tor_bridges_use_custom_bridges']):
reboot_onion = True
else:
common.log('SettingsDialog', 'save_clicked', 'Not connected to Tor')
# Tor isn't connected, so try connecting
reboot_onion = True
else:
self.common.log('SettingsDialog', 'save_clicked', 'Not connected to Tor')
# 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()
# Do we need to reinitialize Tor?
if reboot_onion:
# Reinitialize the Onion object
self.common.log('SettingsDialog', 'save_clicked', 'rebooting the Onion')
self.onion.cleanup()
tor_con = TorConnectionDialog(self.qtapp, settings, self.onion)
tor_con.start()
tor_con = TorConnectionDialog(self.common, self.qtapp, self.onion, settings)
tor_con.start()
common.log('SettingsDialog', 'save_clicked', 'Onion done rebooting, connected to Tor: {}'.format(self.onion.connected_to_tor))
self.common.log('SettingsDialog', 'save_clicked', 'Onion done rebooting, connected to Tor: {}'.format(self.onion.connected_to_tor))
if self.onion.is_authenticated() and not tor_con.wasCanceled():
self.settings_saved.emit()
self.close()
if self.onion.is_authenticated() and not tor_con.wasCanceled():
else:
self.settings_saved.emit()
self.close()
else:
self.settings_saved.emit()
self.close()
@ -859,11 +870,12 @@ class SettingsDialog(QtWidgets.QDialog):
self.common.log('SettingsDialog', 'closeEvent')
# On close, if Tor isn't connected, then quit OnionShare altogether
if not self.onion.is_authenticated():
self.common.log('SettingsDialog', 'closeEvent', 'Closing while not connected to Tor')
if not self.local_only:
if not self.onion.is_authenticated():
self.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)
# Wait 1ms for the event loop to finish, then quit
QtCore.QTimer.singleShot(1, self.qtapp.quit)
def _update_autoupdate_timestamp(self, autoupdate_timestamp):
self.common.log('SettingsDialog', '_update_autoupdate_timestamp')

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 B

View File

@ -48,14 +48,16 @@
"gui_stop_server_shutdown_timeout_tooltip": "Share will stop automatically at {}",
"gui_copy_url": "Copy Address",
"gui_copy_hidservauth": "Copy HidServAuth",
"gui_downloads": "Downloads:",
"gui_downloads": "Download History",
"gui_downloads_window_tooltip": "Show/hide downloads",
"gui_no_downloads": "No downloads yet.",
"gui_canceled": "Canceled",
"gui_copied_url_title": "Copied OnionShare address",
"gui_copied_url": "The OnionShare address has been copied to clipboard",
"gui_copied_hidservauth_title": "Copied HidServAuth",
"gui_copied_hidservauth": "The HidServAuth line has been copied to clipboard",
"gui_starting_server1": "Starting Tor onion service...",
"gui_starting_server2": "Crunching files...",
"gui_starting_server2": "Compressing files...",
"gui_please_wait": "Starting... Click to cancel",
"error_hs_dir_cannot_create": "Cannot create onion service dir {0:s}",
"error_hs_dir_not_writable": "onion service dir {0:s} is not writable",
@ -69,7 +71,7 @@
"gui_quit_warning_quit": "Quit",
"gui_quit_warning_dont_quit": "Cancel",
"error_rate_limit": "An attacker might be trying to guess your address. To prevent this, OnionShare has automatically stopped the server. To share the files you must start it again and share the new address.",
"zip_progress_bar_format": "Crunching files: %p%",
"zip_progress_bar_format": "Compressing 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 Tor 0.2.7.1 and at least python3-stem 1.4.0.",
"gui_settings_window_title": "Settings",
@ -108,6 +110,7 @@
"gui_settings_tor_bridges_meek_lite_amazon_radio_option_no_obfs4proxy": "Use built-in meek_lite (Amazon) pluggable transports (requires obfs4proxy)",
"gui_settings_tor_bridges_meek_lite_azure_radio_option": "Use built-in meek_lite (Azure) pluggable transports",
"gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy": "Use built-in meek_lite (Azure) pluggable transports (requires obfs4proxy)",
"gui_settings_meek_lite_expensive_warning": "Warning: the meek_lite bridges are very costly for the Tor Project to run!<br><br>You should only use meek_lite bridges if you are having trouble connecting to Tor directly, via obfs4 transports or other normal bridges.",
"gui_settings_tor_bridges_custom_radio_option": "Use custom bridges",
"gui_settings_tor_bridges_custom_label": "You can get bridges from <a href=\"https://bridges.torproject.org/options\">https://bridges.torproject.org</a>",
"gui_settings_tor_bridges_invalid": "None of the bridges you supplied seem to be valid.\nPlease try again with valid bridges.",

View File

@ -34,7 +34,7 @@
"gui_copied_url": "URL kopiita en tondujon",
"gui_copied_hidservauth": "Copied HidServAuth line to clipboard",
"gui_starting_server1": "Startigas Tor onion service...",
"gui_starting_server2": "Crunching files...",
"gui_starting_server2": "Compressing files...",
"gui_please_wait": "Bonvolu atendi...",
"error_hs_dir_cannot_create": "Ne eblas krei hidden-service-dosierujon {0:s}",
"error_hs_dir_not_writable": "ne eblas konservi dosierojn en hidden-service-dosierujo {0:s}",
@ -47,7 +47,7 @@
"gui_quit_warning_quit": "Foriri",
"gui_quit_warning_dont_quit": "Ne foriri",
"error_rate_limit": "Iu atankanto povas provi diveni vian URL. Por eviti tion, OnionShare aŭtomate haltis la servilon. Por kundividi la dosierojn vi devas starti ĝin denove kaj kundividi la novan URL.",
"zip_progress_bar_format": "Crunching files: %p%",
"zip_progress_bar_format": "Compressing 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 postulas almenaŭ Tor 0.2.7.1 kaj almenaŭ python3-stem 1.4.0.",
"gui_menu_file_menu": "&File",