aboutsummaryrefslogtreecommitdiff
path: root/onionshare_gui/settings_dialog.py
diff options
context:
space:
mode:
Diffstat (limited to 'onionshare_gui/settings_dialog.py')
-rw-r--r--onionshare_gui/settings_dialog.py650
1 files changed, 423 insertions, 227 deletions
diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py
index c2dca97c..2933784c 100644
--- a/onionshare_gui/settings_dialog.py
+++ b/onionshare_gui/settings_dialog.py
@@ -2,7 +2,7 @@
"""
OnionShare | https://onionshare.org/
-Copyright (C) 2018 Micah Lee <micah@micahflee.com>
+Copyright (C) 2014-2018 Micah Lee <micah@micahflee.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@ from onionshare import strings, common
from onionshare.settings import Settings
from onionshare.onion import *
-from .alert import Alert
+from .widgets import Alert
from .update_checker import *
from .tor_connection_dialog import TorConnectionDialog
@@ -34,93 +34,194 @@ class SettingsDialog(QtWidgets.QDialog):
"""
settings_saved = QtCore.pyqtSignal()
- def __init__(self, onion, qtapp, config=False):
+ def __init__(self, common, onion, qtapp, config=False, local_only=False):
super(SettingsDialog, self).__init__()
- common.log('SettingsDialog', '__init__')
+
+ self.common = common
+
+ self.common.log('SettingsDialog', '__init__')
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))
- self.setWindowIcon(QtGui.QIcon(common.get_resource_path('images/logo.png')))
+ self.setWindowTitle(strings._('gui_settings_window_title'))
+ self.setWindowIcon(QtGui.QIcon(self.common.get_resource_path('images/logo.png')))
self.system = platform.system()
- # Sharing options
-
- # Close after first download
- self.close_after_first_download_checkbox = QtWidgets.QCheckBox()
- self.close_after_first_download_checkbox.setCheckState(QtCore.Qt.Checked)
- self.close_after_first_download_checkbox.setText(strings._("gui_settings_close_after_first_download_option", True))
-
- # Whether or not to show systray notifications
- self.systray_notifications_checkbox = QtWidgets.QCheckBox()
- self.systray_notifications_checkbox.setCheckState(QtCore.Qt.Checked)
- self.systray_notifications_checkbox.setText(strings._("gui_settings_systray_notifications", True))
-
- # Whether or not to use a shutdown timer
+ # General settings
+
+ # Use a slug or not ('public mode')
+ self.public_mode_checkbox = QtWidgets.QCheckBox()
+ self.public_mode_checkbox.setCheckState(QtCore.Qt.Unchecked)
+ self.public_mode_checkbox.setText(strings._("gui_settings_public_mode_checkbox"))
+ public_mode_label = QtWidgets.QLabel(strings._("gui_settings_whats_this").format("https://github.com/micahflee/onionshare/wiki/Public-Mode"))
+ public_mode_label.setStyleSheet(self.common.css['settings_whats_this'])
+ public_mode_label.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
+ public_mode_label.setOpenExternalLinks(True)
+ public_mode_label.setMinimumSize(public_mode_label.sizeHint())
+ public_mode_layout = QtWidgets.QHBoxLayout()
+ public_mode_layout.addWidget(self.public_mode_checkbox)
+ public_mode_layout.addWidget(public_mode_label)
+ public_mode_layout.addStretch()
+ public_mode_layout.setContentsMargins(0,0,0,0)
+ self.public_mode_widget = QtWidgets.QWidget()
+ self.public_mode_widget.setLayout(public_mode_layout)
+
+ # Whether or not to use a shutdown ('auto-stop') timer
self.shutdown_timeout_checkbox = QtWidgets.QCheckBox()
self.shutdown_timeout_checkbox.setCheckState(QtCore.Qt.Checked)
- self.shutdown_timeout_checkbox.setText(strings._("gui_settings_shutdown_timeout_checkbox", True))
-
- # Whether or not to save the Onion private key for reuse
+ self.shutdown_timeout_checkbox.setText(strings._("gui_settings_shutdown_timeout_checkbox"))
+ shutdown_timeout_label = QtWidgets.QLabel(strings._("gui_settings_whats_this").format("https://github.com/micahflee/onionshare/wiki/Using-the-Auto-Stop-Timer"))
+ shutdown_timeout_label.setStyleSheet(self.common.css['settings_whats_this'])
+ shutdown_timeout_label.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
+ shutdown_timeout_label.setOpenExternalLinks(True)
+ shutdown_timeout_label.setMinimumSize(public_mode_label.sizeHint())
+ shutdown_timeout_layout = QtWidgets.QHBoxLayout()
+ shutdown_timeout_layout.addWidget(self.shutdown_timeout_checkbox)
+ shutdown_timeout_layout.addWidget(shutdown_timeout_label)
+ shutdown_timeout_layout.addStretch()
+ shutdown_timeout_layout.setContentsMargins(0,0,0,0)
+ self.shutdown_timeout_widget = QtWidgets.QWidget()
+ self.shutdown_timeout_widget.setLayout(shutdown_timeout_layout)
+
+ # General settings layout
+ general_group_layout = QtWidgets.QVBoxLayout()
+ general_group_layout.addWidget(self.public_mode_widget)
+ general_group_layout.addWidget(self.shutdown_timeout_widget)
+ general_group = QtWidgets.QGroupBox(strings._("gui_settings_general_label"))
+ general_group.setLayout(general_group_layout)
+
+ # Onion settings
+
+ # Label telling user to connect to Tor for onion service settings
+ self.connect_to_tor_label = QtWidgets.QLabel(strings._("gui_connect_to_tor_for_onion_settings"))
+ self.connect_to_tor_label.setStyleSheet(self.common.css['settings_connect_to_tor'])
+
+ # Whether or not to save the Onion private key for reuse (persistent URL mode)
self.save_private_key_checkbox = QtWidgets.QCheckBox()
self.save_private_key_checkbox.setCheckState(QtCore.Qt.Unchecked)
- self.save_private_key_checkbox.setText(strings._("gui_save_private_key_checkbox", True))
-
- # Sharing options layout
- sharing_group_layout = QtWidgets.QVBoxLayout()
- sharing_group_layout.addWidget(self.close_after_first_download_checkbox)
- sharing_group_layout.addWidget(self.systray_notifications_checkbox)
- sharing_group_layout.addWidget(self.shutdown_timeout_checkbox)
- sharing_group_layout.addWidget(self.save_private_key_checkbox)
- sharing_group = QtWidgets.QGroupBox(strings._("gui_settings_sharing_label", True))
- sharing_group.setLayout(sharing_group_layout)
-
- # Stealth options
+ self.save_private_key_checkbox.setText(strings._("gui_save_private_key_checkbox"))
+ save_private_key_label = QtWidgets.QLabel(strings._("gui_settings_whats_this").format("https://github.com/micahflee/onionshare/wiki/Using-a-Persistent-URL"))
+ save_private_key_label.setStyleSheet(self.common.css['settings_whats_this'])
+ save_private_key_label.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
+ save_private_key_label.setOpenExternalLinks(True)
+ save_private_key_layout = QtWidgets.QHBoxLayout()
+ save_private_key_layout.addWidget(self.save_private_key_checkbox)
+ save_private_key_layout.addWidget(save_private_key_label)
+ save_private_key_layout.addStretch()
+ save_private_key_layout.setContentsMargins(0,0,0,0)
+ self.save_private_key_widget = QtWidgets.QWidget()
+ self.save_private_key_widget.setLayout(save_private_key_layout)
+
+ # Whether or not to use legacy v2 onions
+ self.use_legacy_v2_onions_checkbox = QtWidgets.QCheckBox()
+ self.use_legacy_v2_onions_checkbox.setCheckState(QtCore.Qt.Unchecked)
+ self.use_legacy_v2_onions_checkbox.setText(strings._("gui_use_legacy_v2_onions_checkbox"))
+ self.use_legacy_v2_onions_checkbox.clicked.connect(self.use_legacy_v2_onions_checkbox_clicked)
+ use_legacy_v2_onions_label = QtWidgets.QLabel(strings._("gui_settings_whats_this").format("https://github.com/micahflee/onionshare/wiki/Legacy-Addresses"))
+ use_legacy_v2_onions_label.setStyleSheet(self.common.css['settings_whats_this'])
+ use_legacy_v2_onions_label.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
+ use_legacy_v2_onions_label.setOpenExternalLinks(True)
+ use_legacy_v2_onions_layout = QtWidgets.QHBoxLayout()
+ use_legacy_v2_onions_layout.addWidget(self.use_legacy_v2_onions_checkbox)
+ use_legacy_v2_onions_layout.addWidget(use_legacy_v2_onions_label)
+ use_legacy_v2_onions_layout.addStretch()
+ use_legacy_v2_onions_layout.setContentsMargins(0,0,0,0)
+ self.use_legacy_v2_onions_widget = QtWidgets.QWidget()
+ self.use_legacy_v2_onions_widget.setLayout(use_legacy_v2_onions_layout)
# Stealth
- stealth_details = QtWidgets.QLabel(strings._("gui_settings_stealth_option_details", True))
- stealth_details.setWordWrap(True)
- stealth_details.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
- stealth_details.setOpenExternalLinks(True)
- stealth_details.setMinimumSize(stealth_details.sizeHint())
self.stealth_checkbox = QtWidgets.QCheckBox()
self.stealth_checkbox.setCheckState(QtCore.Qt.Unchecked)
- self.stealth_checkbox.setText(strings._("gui_settings_stealth_option", True))
-
- hidservauth_details = QtWidgets.QLabel(strings._('gui_settings_stealth_hidservauth_string', True))
- hidservauth_details.setWordWrap(True)
- hidservauth_details.setMinimumSize(hidservauth_details.sizeHint())
- hidservauth_details.hide()
-
- self.hidservauth_copy_button = QtWidgets.QPushButton(strings._('gui_copy_hidservauth', True))
+ self.stealth_checkbox.setText(strings._("gui_settings_stealth_option"))
+ self.stealth_checkbox.clicked.connect(self.stealth_checkbox_clicked_connect)
+ use_stealth_label = QtWidgets.QLabel(strings._("gui_settings_whats_this").format("https://github.com/micahflee/onionshare/wiki/Stealth-Onion-Services"))
+ use_stealth_label.setStyleSheet(self.common.css['settings_whats_this'])
+ use_stealth_label.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
+ use_stealth_label.setOpenExternalLinks(True)
+ use_stealth_label.setMinimumSize(use_stealth_label.sizeHint())
+ use_stealth_layout = QtWidgets.QHBoxLayout()
+ use_stealth_layout.addWidget(self.stealth_checkbox)
+ use_stealth_layout.addWidget(use_stealth_label)
+ use_stealth_layout.addStretch()
+ use_stealth_layout.setContentsMargins(0,0,0,0)
+ self.use_stealth_widget = QtWidgets.QWidget()
+ self.use_stealth_widget.setLayout(use_stealth_layout)
+
+ self.hidservauth_details = QtWidgets.QLabel(strings._('gui_settings_stealth_hidservauth_string'))
+ self.hidservauth_details.setWordWrap(True)
+ self.hidservauth_details.setMinimumSize(self.hidservauth_details.sizeHint())
+ self.hidservauth_details.hide()
+
+ self.hidservauth_copy_button = QtWidgets.QPushButton(strings._('gui_copy_hidservauth'))
self.hidservauth_copy_button.clicked.connect(self.hidservauth_copy_button_clicked)
self.hidservauth_copy_button.hide()
- # Stealth options layout
- stealth_group_layout = QtWidgets.QVBoxLayout()
- stealth_group_layout.addWidget(stealth_details)
- stealth_group_layout.addWidget(self.stealth_checkbox)
- stealth_group_layout.addWidget(hidservauth_details)
- stealth_group_layout.addWidget(self.hidservauth_copy_button)
- stealth_group = QtWidgets.QGroupBox(strings._("gui_settings_stealth_label", True))
- stealth_group.setLayout(stealth_group_layout)
+ # Onion settings widget
+ onion_settings_layout = QtWidgets.QVBoxLayout()
+ onion_settings_layout.setContentsMargins(0, 0, 0, 0)
+ onion_settings_layout.addWidget(self.save_private_key_widget)
+ onion_settings_layout.addWidget(self.use_legacy_v2_onions_widget)
+ onion_settings_layout.addWidget(self.use_stealth_widget)
+ onion_settings_layout.addWidget(self.hidservauth_details)
+ onion_settings_layout.addWidget(self.hidservauth_copy_button)
+ self.onion_settings_widget = QtWidgets.QWidget()
+ self.onion_settings_widget.setLayout(onion_settings_layout)
+
+ # Onion settings layout
+ onion_group_layout = QtWidgets.QVBoxLayout()
+ onion_group_layout.addWidget(self.connect_to_tor_label)
+ onion_group_layout.addWidget(self.onion_settings_widget)
+ onion_group = QtWidgets.QGroupBox(strings._("gui_settings_onion_label"))
+ onion_group.setLayout(onion_group_layout)
+
+
+ # Sharing options
+
+ # Close after first download
+ self.close_after_first_download_checkbox = QtWidgets.QCheckBox()
+ self.close_after_first_download_checkbox.setCheckState(QtCore.Qt.Checked)
+ self.close_after_first_download_checkbox.setText(strings._("gui_settings_close_after_first_download_option"))
+
+ # Sharing options layout
+ sharing_group_layout = QtWidgets.QVBoxLayout()
+ sharing_group_layout.addWidget(self.close_after_first_download_checkbox)
+ sharing_group = QtWidgets.QGroupBox(strings._("gui_settings_sharing_label"))
+ sharing_group.setLayout(sharing_group_layout)
+
+ # OnionShare data dir
+ data_dir_label = QtWidgets.QLabel(strings._('gui_settings_data_dir_label'));
+ self.data_dir_lineedit = QtWidgets.QLineEdit()
+ self.data_dir_lineedit.setReadOnly(True)
+ data_dir_button = QtWidgets.QPushButton(strings._('gui_settings_data_dir_browse_button'))
+ data_dir_button.clicked.connect(self.data_dir_button_clicked)
+ data_dir_layout = QtWidgets.QHBoxLayout()
+ data_dir_layout.addWidget(data_dir_label)
+ data_dir_layout.addWidget(self.data_dir_lineedit)
+ data_dir_layout.addWidget(data_dir_button)
+
+ # Receiving options layout
+ receiving_group_layout = QtWidgets.QVBoxLayout()
+ receiving_group_layout.addLayout(data_dir_layout)
+ receiving_group = QtWidgets.QGroupBox(strings._("gui_settings_receiving_label"))
+ receiving_group.setLayout(receiving_group_layout)
# Automatic updates options
# Autoupdate
self.autoupdate_checkbox = QtWidgets.QCheckBox()
self.autoupdate_checkbox.setCheckState(QtCore.Qt.Unchecked)
- self.autoupdate_checkbox.setText(strings._("gui_settings_autoupdate_option", True))
+ self.autoupdate_checkbox.setText(strings._("gui_settings_autoupdate_option"))
# Last update time
self.autoupdate_timestamp = QtWidgets.QLabel()
# Check for updates button
- self.check_for_updates_button = QtWidgets.QPushButton(strings._('gui_settings_autoupdate_check_button', True))
+ self.check_for_updates_button = QtWidgets.QPushButton(strings._('gui_settings_autoupdate_check_button'))
self.check_for_updates_button.clicked.connect(self.check_for_updates)
# We can't check for updates if not connected to Tor
if not self.onion.connected_to_tor:
@@ -131,17 +232,32 @@ class SettingsDialog(QtWidgets.QDialog):
autoupdate_group_layout.addWidget(self.autoupdate_checkbox)
autoupdate_group_layout.addWidget(self.autoupdate_timestamp)
autoupdate_group_layout.addWidget(self.check_for_updates_button)
- autoupdate_group = QtWidgets.QGroupBox(strings._("gui_settings_autoupdate_label", True))
+ autoupdate_group = QtWidgets.QGroupBox(strings._("gui_settings_autoupdate_label"))
autoupdate_group.setLayout(autoupdate_group_layout)
# Autoupdate is only available for Windows and Mac (Linux updates using package manager)
if self.system != 'Windows' and self.system != 'Darwin':
autoupdate_group.hide()
+ # Language settings
+ language_label = QtWidgets.QLabel(strings._("gui_settings_language_label"))
+ self.language_combobox = QtWidgets.QComboBox()
+ # Populate the dropdown with all of OnionShare's available languages
+ language_names_to_locales = {v: k for k, v in self.common.settings.available_locales.items()}
+ language_names = list(language_names_to_locales)
+ language_names.sort()
+ for language_name in language_names:
+ locale = language_names_to_locales[language_name]
+ self.language_combobox.addItem(language_name, QtCore.QVariant(locale))
+ language_layout = QtWidgets.QHBoxLayout()
+ language_layout.addWidget(language_label)
+ language_layout.addWidget(self.language_combobox)
+ language_layout.addStretch()
+
# Connection type: either automatic, control port, or socket file
# Bundled Tor
- self.connection_type_bundled_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_bundled_option', True))
+ self.connection_type_bundled_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_bundled_option'))
self.connection_type_bundled_radio.toggled.connect(self.connection_type_bundled_toggled)
# Bundled Tor doesn't work on dev mode in Windows or Mac
@@ -151,49 +267,34 @@ class SettingsDialog(QtWidgets.QDialog):
# Bridge options for bundled tor
# No bridges option radio
- self.tor_bridges_no_bridges_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_no_bridges_radio_option', True))
+ self.tor_bridges_no_bridges_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_no_bridges_radio_option'))
self.tor_bridges_no_bridges_radio.toggled.connect(self.tor_bridges_no_bridges_radio_toggled)
# obfs4 option radio
# if the obfs4proxy binary is missing, we can't use obfs4 transports
- (self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path) = common.get_tor_paths()
+ (self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path) = self.common.get_tor_paths()
if not os.path.isfile(self.obfs4proxy_file_path):
- self.tor_bridges_use_obfs4_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy', True))
+ self.tor_bridges_use_obfs4_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy'))
self.tor_bridges_use_obfs4_radio.setEnabled(False)
else:
- self.tor_bridges_use_obfs4_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_obfs4_radio_option', True))
+ self.tor_bridges_use_obfs4_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_obfs4_radio_option'))
self.tor_bridges_use_obfs4_radio.toggled.connect(self.tor_bridges_use_obfs4_radio_toggled)
- # meek_lite-amazon option radio
- # if the obfs4proxy binary is missing, we can't use meek_lite-amazon transports
- (self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path) = common.get_tor_paths()
- if not os.path.isfile(self.obfs4proxy_file_path):
- self.tor_bridges_use_meek_lite_amazon_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_meek_lite_amazon_radio_option_no_obfs4proxy', True))
- self.tor_bridges_use_meek_lite_amazon_radio.setEnabled(False)
- else:
- self.tor_bridges_use_meek_lite_amazon_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_meek_lite_amazon_radio_option', True))
- self.tor_bridges_use_meek_lite_amazon_radio.toggled.connect(self.tor_bridges_use_meek_lite_amazon_radio_toggled)
-
# meek_lite-azure option radio
# if the obfs4proxy binary is missing, we can't use meek_lite-azure transports
- (self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path) = common.get_tor_paths()
+ (self.tor_path, self.tor_geo_ip_file_path, self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path) = self.common.get_tor_paths()
if not os.path.isfile(self.obfs4proxy_file_path):
- self.tor_bridges_use_meek_lite_azure_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy', True))
+ self.tor_bridges_use_meek_lite_azure_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy'))
self.tor_bridges_use_meek_lite_azure_radio.setEnabled(False)
else:
- self.tor_bridges_use_meek_lite_azure_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_meek_lite_azure_radio_option', True))
+ self.tor_bridges_use_meek_lite_azure_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_meek_lite_azure_radio_option'))
self.tor_bridges_use_meek_lite_azure_radio.toggled.connect(self.tor_bridges_use_meek_lite_azure_radio_toggled)
- # meek_lite currently not supported on the version of obfs4proxy bundled with TorBrowser
- if self.system == 'Windows' or self.system == 'Darwin':
- self.tor_bridges_use_meek_lite_amazon_radio.hide()
- self.tor_bridges_use_meek_lite_azure_radio.hide()
-
# Custom bridges radio and textbox
- self.tor_bridges_use_custom_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_custom_radio_option', True))
+ self.tor_bridges_use_custom_radio = QtWidgets.QRadioButton(strings._('gui_settings_tor_bridges_custom_radio_option'))
self.tor_bridges_use_custom_radio.toggled.connect(self.tor_bridges_use_custom_radio_toggled)
- self.tor_bridges_use_custom_label = QtWidgets.QLabel(strings._('gui_settings_tor_bridges_custom_label', True))
+ self.tor_bridges_use_custom_label = QtWidgets.QLabel(strings._('gui_settings_tor_bridges_custom_label'))
self.tor_bridges_use_custom_label.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
self.tor_bridges_use_custom_label.setOpenExternalLinks(True)
self.tor_bridges_use_custom_textbox = QtWidgets.QPlainTextEdit()
@@ -212,7 +313,6 @@ class SettingsDialog(QtWidgets.QDialog):
bridges_layout = QtWidgets.QVBoxLayout()
bridges_layout.addWidget(self.tor_bridges_no_bridges_radio)
bridges_layout.addWidget(self.tor_bridges_use_obfs4_radio)
- bridges_layout.addWidget(self.tor_bridges_use_meek_lite_amazon_radio)
bridges_layout.addWidget(self.tor_bridges_use_meek_lite_azure_radio)
bridges_layout.addWidget(self.tor_bridges_use_custom_radio)
bridges_layout.addWidget(self.tor_bridges_use_custom_textbox_options)
@@ -221,14 +321,14 @@ class SettingsDialog(QtWidgets.QDialog):
self.bridges.setLayout(bridges_layout)
# Automatic
- self.connection_type_automatic_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_automatic_option', True))
+ self.connection_type_automatic_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_automatic_option'))
self.connection_type_automatic_radio.toggled.connect(self.connection_type_automatic_toggled)
# Control port
- self.connection_type_control_port_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_control_port_option', True))
+ self.connection_type_control_port_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_control_port_option'))
self.connection_type_control_port_radio.toggled.connect(self.connection_type_control_port_toggled)
- connection_type_control_port_extras_label = QtWidgets.QLabel(strings._('gui_settings_control_port_label', True))
+ connection_type_control_port_extras_label = QtWidgets.QLabel(strings._('gui_settings_control_port_label'))
self.connection_type_control_port_extras_address = QtWidgets.QLineEdit()
self.connection_type_control_port_extras_port = QtWidgets.QLineEdit()
connection_type_control_port_extras_layout = QtWidgets.QHBoxLayout()
@@ -241,10 +341,10 @@ class SettingsDialog(QtWidgets.QDialog):
self.connection_type_control_port_extras.hide()
# Socket file
- self.connection_type_socket_file_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_socket_file_option', True))
+ self.connection_type_socket_file_radio = QtWidgets.QRadioButton(strings._('gui_settings_connection_type_socket_file_option'))
self.connection_type_socket_file_radio.toggled.connect(self.connection_type_socket_file_toggled)
- connection_type_socket_file_extras_label = QtWidgets.QLabel(strings._('gui_settings_socket_file_label', True))
+ connection_type_socket_file_extras_label = QtWidgets.QLabel(strings._('gui_settings_socket_file_label'))
self.connection_type_socket_file_extras_path = QtWidgets.QLineEdit()
connection_type_socket_file_extras_layout = QtWidgets.QHBoxLayout()
connection_type_socket_file_extras_layout.addWidget(connection_type_socket_file_extras_label)
@@ -255,7 +355,7 @@ class SettingsDialog(QtWidgets.QDialog):
self.connection_type_socket_file_extras.hide()
# Tor SOCKS address and port
- gui_settings_socks_label = QtWidgets.QLabel(strings._('gui_settings_socks_label', True))
+ gui_settings_socks_label = QtWidgets.QLabel(strings._('gui_settings_socks_label'))
self.connection_type_socks_address = QtWidgets.QLineEdit()
self.connection_type_socks_port = QtWidgets.QLineEdit()
connection_type_socks_layout = QtWidgets.QHBoxLayout()
@@ -270,14 +370,14 @@ class SettingsDialog(QtWidgets.QDialog):
# Authentication options
# No authentication
- self.authenticate_no_auth_radio = QtWidgets.QRadioButton(strings._('gui_settings_authenticate_no_auth_option', True))
+ self.authenticate_no_auth_radio = QtWidgets.QRadioButton(strings._('gui_settings_authenticate_no_auth_option'))
self.authenticate_no_auth_radio.toggled.connect(self.authenticate_no_auth_toggled)
# Password
- self.authenticate_password_radio = QtWidgets.QRadioButton(strings._('gui_settings_authenticate_password_option', True))
+ self.authenticate_password_radio = QtWidgets.QRadioButton(strings._('gui_settings_authenticate_password_option'))
self.authenticate_password_radio.toggled.connect(self.authenticate_password_toggled)
- authenticate_password_extras_label = QtWidgets.QLabel(strings._('gui_settings_password_label', True))
+ authenticate_password_extras_label = QtWidgets.QLabel(strings._('gui_settings_password_label'))
self.authenticate_password_extras_password = QtWidgets.QLineEdit('')
authenticate_password_extras_layout = QtWidgets.QHBoxLayout()
authenticate_password_extras_layout.addWidget(authenticate_password_extras_label)
@@ -292,47 +392,49 @@ class SettingsDialog(QtWidgets.QDialog):
authenticate_group_layout.addWidget(self.authenticate_no_auth_radio)
authenticate_group_layout.addWidget(self.authenticate_password_radio)
authenticate_group_layout.addWidget(self.authenticate_password_extras)
- self.authenticate_group = QtWidgets.QGroupBox(strings._("gui_settings_authenticate_label", True))
+ self.authenticate_group = QtWidgets.QGroupBox(strings._("gui_settings_authenticate_label"))
self.authenticate_group.setLayout(authenticate_group_layout)
- # Test tor settings button
- self.connection_type_test_button = QtWidgets.QPushButton(strings._('gui_settings_connection_type_test_button', True))
- self.connection_type_test_button.clicked.connect(self.test_tor_clicked)
-
# Put the radios into their own group so they are exclusive
connection_type_radio_group_layout = QtWidgets.QVBoxLayout()
connection_type_radio_group_layout.addWidget(self.connection_type_bundled_radio)
connection_type_radio_group_layout.addWidget(self.connection_type_automatic_radio)
connection_type_radio_group_layout.addWidget(self.connection_type_control_port_radio)
connection_type_radio_group_layout.addWidget(self.connection_type_socket_file_radio)
- connection_type_radio_group = QtWidgets.QGroupBox(strings._("gui_settings_connection_type_label", True))
+ connection_type_radio_group = QtWidgets.QGroupBox(strings._("gui_settings_connection_type_label"))
connection_type_radio_group.setLayout(connection_type_radio_group_layout)
- # Connection type layout
- connection_type_group_layout = QtWidgets.QVBoxLayout()
- connection_type_group_layout.addWidget(self.connection_type_control_port_extras)
- connection_type_group_layout.addWidget(self.connection_type_socket_file_extras)
- connection_type_group_layout.addWidget(self.connection_type_socks)
- connection_type_group_layout.addWidget(self.authenticate_group)
- connection_type_group_layout.addWidget(self.connection_type_test_button)
- connection_type_group = QtWidgets.QGroupBox()
- connection_type_group.setLayout(connection_type_group_layout)
-
# The Bridges options are not exclusive (enabling Bridges offers obfs4 or custom bridges)
connection_type_bridges_radio_group_layout = QtWidgets.QVBoxLayout()
connection_type_bridges_radio_group_layout.addWidget(self.bridges)
- self.connection_type_bridges_radio_group = QtWidgets.QGroupBox(strings._("gui_settings_tor_bridges", True))
+ self.connection_type_bridges_radio_group = QtWidgets.QGroupBox(strings._("gui_settings_tor_bridges"))
self.connection_type_bridges_radio_group.setLayout(connection_type_bridges_radio_group_layout)
self.connection_type_bridges_radio_group.hide()
+ # Test tor settings button
+ self.connection_type_test_button = QtWidgets.QPushButton(strings._('gui_settings_connection_type_test_button'))
+ self.connection_type_test_button.clicked.connect(self.test_tor_clicked)
+ connection_type_test_button_layout = QtWidgets.QHBoxLayout()
+ connection_type_test_button_layout.addWidget(self.connection_type_test_button)
+ connection_type_test_button_layout.addStretch()
+
+ # Connection type layout
+ connection_type_layout = QtWidgets.QVBoxLayout()
+ connection_type_layout.addWidget(self.connection_type_control_port_extras)
+ connection_type_layout.addWidget(self.connection_type_socket_file_extras)
+ connection_type_layout.addWidget(self.connection_type_socks)
+ connection_type_layout.addWidget(self.authenticate_group)
+ connection_type_layout.addWidget(self.connection_type_bridges_radio_group)
+ connection_type_layout.addLayout(connection_type_test_button_layout)
+
# Buttons
- self.save_button = QtWidgets.QPushButton(strings._('gui_settings_button_save', True))
+ self.save_button = QtWidgets.QPushButton(strings._('gui_settings_button_save'))
self.save_button.clicked.connect(self.save_clicked)
- self.cancel_button = QtWidgets.QPushButton(strings._('gui_settings_button_cancel', True))
+ self.cancel_button = QtWidgets.QPushButton(strings._('gui_settings_button_cancel'))
self.cancel_button.clicked.connect(self.cancel_clicked)
- version_label = QtWidgets.QLabel('OnionShare {0:s}'.format(common.get_version()))
- version_label.setStyleSheet('color: #666666')
- self.help_button = QtWidgets.QPushButton(strings._('gui_settings_button_help', True))
+ version_label = QtWidgets.QLabel('OnionShare {0:s}'.format(self.common.version))
+ version_label.setStyleSheet(self.common.css['settings_version'])
+ self.help_button = QtWidgets.QPushButton(strings._('gui_settings_button_help'))
self.help_button.clicked.connect(self.help_clicked)
buttons_layout = QtWidgets.QHBoxLayout()
buttons_layout.addWidget(version_label)
@@ -343,20 +445,22 @@ class SettingsDialog(QtWidgets.QDialog):
# Tor network connection status
self.tor_status = QtWidgets.QLabel()
- self.tor_status.setStyleSheet('background-color: #ffffff; color: #000000; padding: 10px')
+ self.tor_status.setStyleSheet(self.common.css['settings_tor_status'])
self.tor_status.hide()
# Layout
left_col_layout = QtWidgets.QVBoxLayout()
+ left_col_layout.addWidget(general_group)
+ left_col_layout.addWidget(onion_group)
left_col_layout.addWidget(sharing_group)
- left_col_layout.addWidget(stealth_group)
+ left_col_layout.addWidget(receiving_group)
left_col_layout.addWidget(autoupdate_group)
+ left_col_layout.addLayout(language_layout)
left_col_layout.addStretch()
right_col_layout = QtWidgets.QVBoxLayout()
right_col_layout.addWidget(connection_type_radio_group)
- right_col_layout.addWidget(connection_type_group)
- right_col_layout.addWidget(self.connection_type_bridges_radio_group)
+ right_col_layout.addLayout(connection_type_layout)
right_col_layout.addWidget(self.tor_status)
right_col_layout.addStretch()
@@ -371,8 +475,11 @@ class SettingsDialog(QtWidgets.QDialog):
self.setLayout(layout)
self.cancel_button.setFocus()
+ self.reload_settings()
+
+ def reload_settings(self):
# Load settings, and fill them in
- self.old_settings = Settings(self.config)
+ self.old_settings = Settings(self.common, self.config)
self.old_settings.load()
close_after_first_download = self.old_settings.get('close_after_first_download')
@@ -381,12 +488,6 @@ class SettingsDialog(QtWidgets.QDialog):
else:
self.close_after_first_download_checkbox.setCheckState(QtCore.Qt.Unchecked)
- systray_notifications = self.old_settings.get('systray_notifications')
- if systray_notifications:
- self.systray_notifications_checkbox.setCheckState(QtCore.Qt.Checked)
- else:
- self.systray_notifications_checkbox.setCheckState(QtCore.Qt.Unchecked)
-
shutdown_timeout = self.old_settings.get('shutdown_timeout')
if shutdown_timeout:
self.shutdown_timeout_checkbox.setCheckState(QtCore.Qt.Checked)
@@ -399,11 +500,30 @@ class SettingsDialog(QtWidgets.QDialog):
else:
self.save_private_key_checkbox.setCheckState(QtCore.Qt.Unchecked)
+ use_legacy_v2_onions = self.old_settings.get('use_legacy_v2_onions')
+
+ if use_legacy_v2_onions:
+ self.use_legacy_v2_onions_checkbox.setCheckState(QtCore.Qt.Checked)
+ self.use_stealth_widget.show()
+ else:
+ self.use_stealth_widget.hide()
+
+ data_dir = self.old_settings.get('data_dir')
+ self.data_dir_lineedit.setText(data_dir)
+
+ public_mode = self.old_settings.get('public_mode')
+ if public_mode:
+ self.public_mode_checkbox.setCheckState(QtCore.Qt.Checked)
+ else:
+ self.public_mode_checkbox.setCheckState(QtCore.Qt.Unchecked)
+
use_stealth = self.old_settings.get('use_stealth')
if use_stealth:
self.stealth_checkbox.setCheckState(QtCore.Qt.Checked)
- if save_private_key:
- hidservauth_details.show()
+ # Legacy v2 mode is forced on if Stealth is enabled
+ self.use_legacy_v2_onions_checkbox.setEnabled(False)
+ if save_private_key and self.old_settings.get('hidservauth_string') != "":
+ self.hidservauth_details.show()
self.hidservauth_copy_button.show()
else:
self.stealth_checkbox.setCheckState(QtCore.Qt.Unchecked)
@@ -417,6 +537,10 @@ class SettingsDialog(QtWidgets.QDialog):
autoupdate_timestamp = self.old_settings.get('autoupdate_timestamp')
self._update_autoupdate_timestamp(autoupdate_timestamp)
+ locale = self.old_settings.get('locale')
+ locale_index = self.language_combobox.findData(QtCore.QVariant(locale))
+ self.language_combobox.setCurrentIndex(locale_index)
+
connection_type = self.old_settings.get('connection_type')
if connection_type == 'bundled':
if self.connection_type_bundled_radio.isEnabled():
@@ -445,13 +569,11 @@ class SettingsDialog(QtWidgets.QDialog):
if self.old_settings.get('no_bridges'):
self.tor_bridges_no_bridges_radio.setChecked(True)
self.tor_bridges_use_obfs4_radio.setChecked(False)
- self.tor_bridges_use_meek_lite_amazon_radio.setChecked(False)
self.tor_bridges_use_meek_lite_azure_radio.setChecked(False)
self.tor_bridges_use_custom_radio.setChecked(False)
else:
self.tor_bridges_no_bridges_radio.setChecked(False)
self.tor_bridges_use_obfs4_radio.setChecked(self.old_settings.get('tor_bridges_use_obfs4'))
- self.tor_bridges_use_meek_lite_amazon_radio.setChecked(self.old_settings.get('tor_bridges_use_meek_lite_amazon'))
self.tor_bridges_use_meek_lite_azure_radio.setChecked(self.old_settings.get('tor_bridges_use_meek_lite_azure'))
if self.old_settings.get('tor_bridges_use_custom_bridges'):
@@ -466,11 +588,29 @@ class SettingsDialog(QtWidgets.QDialog):
new_bridges = ''.join(new_bridges)
self.tor_bridges_use_custom_textbox.setPlainText(new_bridges)
+ # If we're connected to Tor, show onion service settings, show label if not
+ if self.onion.is_authenticated():
+ self.connect_to_tor_label.hide()
+ self.onion_settings_widget.show()
+
+ # If v3 onion services are supported, allow using legacy mode
+ if self.onion.supports_v3_onions:
+ self.common.log('SettingsDialog', '__init__', 'v3 onions are supported')
+ self.use_legacy_v2_onions_checkbox.show()
+ else:
+ self.common.log('SettingsDialog', '__init__', 'v3 onions are not supported')
+ self.use_legacy_v2_onions_widget.hide()
+ self.use_legacy_v2_onions_checkbox_clicked(True)
+ else:
+ self.connect_to_tor_label.show()
+ self.onion_settings_widget.hide()
+
+
def connection_type_bundled_toggled(self, checked):
"""
Connection type bundled was toggled. If checked, hide authentication fields.
"""
- common.log('SettingsDialog', 'connection_type_bundled_toggled')
+ self.common.log('SettingsDialog', 'connection_type_bundled_toggled')
if checked:
self.authenticate_group.hide()
self.connection_type_socks.hide()
@@ -490,19 +630,15 @@ class SettingsDialog(QtWidgets.QDialog):
if checked:
self.tor_bridges_use_custom_textbox_options.hide()
- def tor_bridges_use_meek_lite_amazon_radio_toggled(self, checked):
- """
- meek_lite-amazon bridges option was toggled. If checked, disable custom bridge options.
- """
- if checked:
- self.tor_bridges_use_custom_textbox_options.hide()
-
def tor_bridges_use_meek_lite_azure_radio_toggled(self, checked):
"""
meek_lite_azure bridges option was toggled. If checked, disable custom bridge options.
"""
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(self.common, strings._('gui_settings_meek_lite_expensive_warning'), QtWidgets.QMessageBox.Warning)
def tor_bridges_use_custom_radio_toggled(self, checked):
"""
@@ -515,7 +651,7 @@ class SettingsDialog(QtWidgets.QDialog):
"""
Connection type automatic was toggled. If checked, hide authentication fields.
"""
- common.log('SettingsDialog', 'connection_type_automatic_toggled')
+ self.common.log('SettingsDialog', 'connection_type_automatic_toggled')
if checked:
self.authenticate_group.hide()
self.connection_type_socks.hide()
@@ -526,7 +662,7 @@ class SettingsDialog(QtWidgets.QDialog):
Connection type control port was toggled. If checked, show extra fields
for Tor control address and port. If unchecked, hide those extra fields.
"""
- common.log('SettingsDialog', 'connection_type_control_port_toggled')
+ self.common.log('SettingsDialog', 'connection_type_control_port_toggled')
if checked:
self.authenticate_group.show()
self.connection_type_control_port_extras.show()
@@ -541,7 +677,7 @@ class SettingsDialog(QtWidgets.QDialog):
Connection type socket file was toggled. If checked, show extra fields
for socket file. If unchecked, hide those extra fields.
"""
- common.log('SettingsDialog', 'connection_type_socket_file_toggled')
+ self.common.log('SettingsDialog', 'connection_type_socket_file_toggled')
if checked:
self.authenticate_group.show()
self.connection_type_socket_file_extras.show()
@@ -554,14 +690,14 @@ class SettingsDialog(QtWidgets.QDialog):
"""
Authentication option no authentication was toggled.
"""
- common.log('SettingsDialog', 'authenticate_no_auth_toggled')
+ self.common.log('SettingsDialog', 'authenticate_no_auth_toggled')
def authenticate_password_toggled(self, checked):
"""
Authentication option password was toggled. If checked, show extra fields
for password auth. If unchecked, hide those extra fields.
"""
- common.log('SettingsDialog', 'authenticate_password_toggled')
+ self.common.log('SettingsDialog', 'authenticate_password_toggled')
if checked:
self.authenticate_password_extras.show()
else:
@@ -572,16 +708,47 @@ class SettingsDialog(QtWidgets.QDialog):
Toggle the 'Copy HidServAuth' button
to copy the saved HidServAuth to clipboard.
"""
- common.log('SettingsDialog', 'hidservauth_copy_button_clicked', 'HidServAuth was copied to clipboard')
+ self.common.log('SettingsDialog', 'hidservauth_copy_button_clicked', 'HidServAuth was copied to clipboard')
clipboard = self.qtapp.clipboard()
clipboard.setText(self.old_settings.get('hidservauth_string'))
+ def use_legacy_v2_onions_checkbox_clicked(self, checked):
+ """
+ Show the legacy settings if the legacy mode is enabled.
+ """
+ if checked:
+ self.use_stealth_widget.show()
+ else:
+ self.use_stealth_widget.hide()
+
+ def stealth_checkbox_clicked_connect(self, checked):
+ """
+ Prevent the v2 legacy mode being switched off if stealth is enabled
+ """
+ if checked:
+ self.use_legacy_v2_onions_checkbox.setCheckState(QtCore.Qt.Checked)
+ self.use_legacy_v2_onions_checkbox.setEnabled(False)
+ else:
+ self.use_legacy_v2_onions_checkbox.setEnabled(True)
+
+ def data_dir_button_clicked(self):
+ """
+ Browse for a new OnionShare data directory
+ """
+ data_dir = self.data_dir_lineedit.text()
+ selected_dir = QtWidgets.QFileDialog.getExistingDirectory(self,
+ strings._('gui_settings_data_dir_label'), data_dir)
+
+ if selected_dir:
+ self.common.log('SettingsDialog', 'data_dir_button_clicked', 'selected dir: {}'.format(selected_dir))
+ self.data_dir_lineedit.setText(selected_dir)
+
def test_tor_clicked(self):
"""
Test Tor Settings button clicked. With the given settings, see if we can
successfully connect and authenticate to Tor.
"""
- common.log('SettingsDialog', 'test_tor_clicked')
+ self.common.log('SettingsDialog', 'test_tor_clicked')
settings = self.settings_from_fields()
try:
@@ -596,17 +763,17 @@ class SettingsDialog(QtWidgets.QDialog):
else:
tor_status_update_func = None
- onion = Onion()
- onion.connect(settings=settings, config=self.config, tor_status_update_func=tor_status_update_func)
+ onion = Onion(self.common)
+ onion.connect(custom_settings=settings, config=self.config, tor_status_update_func=tor_status_update_func)
# If an exception hasn't been raised yet, the Tor settings work
- Alert(strings._('settings_test_success', True).format(onion.tor_version, onion.supports_ephemeral, onion.supports_stealth))
+ Alert(self.common, strings._('settings_test_success').format(onion.tor_version, onion.supports_ephemeral, onion.supports_stealth, onion.supports_v3_onions))
# Clean up
onion.cleanup()
except (TorErrorInvalidSetting, TorErrorAutomatic, TorErrorSocketPort, TorErrorSocketFile, TorErrorMissingPassword, TorErrorUnreadableCookieFile, TorErrorAuthError, TorErrorProtocolError, BundledTorNotSupported, BundledTorTimeout) as e:
- Alert(e.args[0], QtWidgets.QMessageBox.Warning)
+ Alert(self.common, e.args[0], QtWidgets.QMessageBox.Warning)
if settings.get('connection_type') == 'bundled':
self.tor_status.hide()
self._enable_buttons()
@@ -615,14 +782,14 @@ class SettingsDialog(QtWidgets.QDialog):
"""
Check for Updates button clicked. Manually force an update check.
"""
- common.log('SettingsDialog', 'check_for_updates')
+ self.common.log('SettingsDialog', 'check_for_updates')
# Disable buttons
self._disable_buttons()
self.qtapp.processEvents()
def update_timestamp():
# Update the last checked label
- settings = Settings(self.config)
+ settings = Settings(self.common, self.config)
settings.load()
autoupdate_timestamp = settings.get('autoupdate_timestamp')
self._update_autoupdate_timestamp(autoupdate_timestamp)
@@ -636,22 +803,22 @@ class SettingsDialog(QtWidgets.QDialog):
# Check for updates
def update_available(update_url, installed_version, latest_version):
- Alert(strings._("update_available", True).format(update_url, installed_version, latest_version))
+ Alert(self.common, strings._("update_available").format(update_url, installed_version, latest_version))
close_forced_update_thread()
def update_not_available():
- Alert(strings._('update_not_available', True))
+ Alert(self.common, strings._('update_not_available'))
close_forced_update_thread()
def update_error():
- Alert(strings._('update_error_check_error', True), QtWidgets.QMessageBox.Warning)
+ Alert(self.common, strings._('update_error_check_error'), QtWidgets.QMessageBox.Warning)
close_forced_update_thread()
- def update_invalid_version():
- Alert(strings._('update_error_invalid_latest_version', True).format(e.latest_version), QtWidgets.QMessageBox.Warning)
+ def update_invalid_version(latest_version):
+ Alert(self.common, strings._('update_error_invalid_latest_version').format(latest_version), QtWidgets.QMessageBox.Warning)
close_forced_update_thread()
- forced_update_thread = UpdateThread(self.onion, self.config, force=True)
+ forced_update_thread = UpdateThread(self.common, self.onion, self.config, force=True)
forced_update_thread.update_available.connect(update_available)
forced_update_thread.update_not_available.connect(update_not_available)
forced_update_thread.update_error.connect(update_error)
@@ -662,57 +829,73 @@ class SettingsDialog(QtWidgets.QDialog):
"""
Save button clicked. Save current settings to disk.
"""
- common.log('SettingsDialog', 'save_clicked')
+ self.common.log('SettingsDialog', 'save_clicked')
+
+ 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
settings = self.settings_from_fields()
if settings:
+ # If language changed, inform user they need to restart OnionShare
+ if changed(settings, self.old_settings, ['locale']):
+ # Look up error message in different locale
+ new_locale = settings.get('locale')
+ if new_locale in strings.translations and 'gui_settings_language_changed_notice' in strings.translations[new_locale]:
+ notice = strings.translations[new_locale]['gui_settings_language_changed_notice']
+ else:
+ notice = strings._('gui_settings_language_changed_notice')
+ Alert(self.common, notice, QtWidgets.QMessageBox.Information)
+
+ # Save the new settings
settings.save()
# If Tor isn't connected, or if Tor settings have changed, Reinitialize
# the Onion object
reboot_onion = False
- 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 not self.local_only:
+ if self.onion.is_authenticated():
+ self.common.log('SettingsDialog', 'save_clicked', 'Connected to Tor')
+
+ 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_azure',
+ 'tor_bridges_use_custom_bridges']):
+
+ reboot_onion = True
+
+ else:
+ self.common.log('SettingsDialog', 'save_clicked', 'Not connected to Tor')
+ # Tor isn't connected, so try connecting
reboot_onion = True
- else:
- 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
+ self.common.log('SettingsDialog', 'save_clicked', 'rebooting the Onion')
+ self.onion.cleanup()
- # Do we need to reinitialize Tor?
- if reboot_onion:
- # Reinitialize the Onion object
- common.log('SettingsDialog', 'save_clicked', 'rebooting the Onion')
- self.onion.cleanup()
+ tor_con = TorConnectionDialog(self.common, self.qtapp, self.onion, settings)
+ tor_con.start()
- tor_con = TorConnectionDialog(self.qtapp, settings, self.onion)
- tor_con.start()
+ self.common.log('SettingsDialog', 'save_clicked', 'Onion done rebooting, connected to Tor: {}'.format(self.onion.connected_to_tor))
- 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()
@@ -721,9 +904,9 @@ class SettingsDialog(QtWidgets.QDialog):
"""
Cancel button clicked.
"""
- common.log('SettingsDialog', 'cancel_clicked')
- if not self.onion.is_authenticated():
- Alert(strings._('gui_tor_connection_canceled', True), QtWidgets.QMessageBox.Warning)
+ self.common.log('SettingsDialog', 'cancel_clicked')
+ if not self.local_only and not self.onion.is_authenticated():
+ Alert(self.common, strings._('gui_tor_connection_canceled'), QtWidgets.QMessageBox.Warning)
sys.exit()
else:
self.close()
@@ -732,21 +915,31 @@ class SettingsDialog(QtWidgets.QDialog):
"""
Help button clicked.
"""
- common.log('SettingsDialog', 'help_clicked')
- help_site = 'https://github.com/micahflee/onionshare/wiki'
- QtGui.QDesktopServices.openUrl(QtCore.QUrl(help_site))
+ self.common.log('SettingsDialog', 'help_clicked')
+ SettingsDialog.open_help()
+
+ @staticmethod
+ def open_help():
+ help_url = 'https://github.com/micahflee/onionshare/wiki'
+ QtGui.QDesktopServices.openUrl(QtCore.QUrl(help_url))
def settings_from_fields(self):
"""
Return a Settings object that's full of values from the settings dialog.
"""
- common.log('SettingsDialog', 'settings_from_fields')
- settings = Settings(self.config)
+ self.common.log('SettingsDialog', 'settings_from_fields')
+ settings = Settings(self.common, self.config)
settings.load() # To get the last update timestamp
settings.set('close_after_first_download', self.close_after_first_download_checkbox.isChecked())
- settings.set('systray_notifications', self.systray_notifications_checkbox.isChecked())
settings.set('shutdown_timeout', self.shutdown_timeout_checkbox.isChecked())
+
+ # Complicated logic here to force v2 onion mode on or off depending on other settings
+ if self.use_legacy_v2_onions_checkbox.isChecked():
+ use_legacy_v2_onions = True
+ else:
+ use_legacy_v2_onions = False
+
if self.save_private_key_checkbox.isChecked():
settings.set('save_private_key', True)
settings.set('private_key', self.old_settings.get('private_key'))
@@ -758,11 +951,25 @@ class SettingsDialog(QtWidgets.QDialog):
settings.set('slug', '')
# Also unset the HidServAuth if we are removing our reusable private key
settings.set('hidservauth_string', '')
+
+ if use_legacy_v2_onions:
+ settings.set('use_legacy_v2_onions', True)
+ else:
+ settings.set('use_legacy_v2_onions', False)
+
+ settings.set('data_dir', self.data_dir_lineedit.text())
+ settings.set('public_mode', self.public_mode_checkbox.isChecked())
settings.set('use_stealth', self.stealth_checkbox.isChecked())
# Always unset the HidServAuth if Stealth mode is unset
if not self.stealth_checkbox.isChecked():
settings.set('hidservauth_string', '')
+ # Language
+ locale_index = self.language_combobox.currentIndex()
+ locale = self.language_combobox.itemData(locale_index)
+ settings.set('locale', locale)
+
+ # Tor connection
if self.connection_type_bundled_radio.isChecked():
settings.set('connection_type', 'bundled')
if self.connection_type_automatic_radio.isChecked():
@@ -795,31 +1002,21 @@ class SettingsDialog(QtWidgets.QDialog):
if self.tor_bridges_no_bridges_radio.isChecked():
settings.set('no_bridges', True)
settings.set('tor_bridges_use_obfs4', False)
- settings.set('tor_bridges_use_meek_lite_amazon', False)
settings.set('tor_bridges_use_meek_lite_azure', False)
settings.set('tor_bridges_use_custom_bridges', '')
if self.tor_bridges_use_obfs4_radio.isChecked():
settings.set('no_bridges', False)
settings.set('tor_bridges_use_obfs4', True)
- settings.set('tor_bridges_use_meek_lite_amazon', False)
- settings.set('tor_bridges_use_meek_lite_azure', False)
- settings.set('tor_bridges_use_custom_bridges', '')
- if self.tor_bridges_use_meek_lite_amazon_radio.isChecked():
- settings.set('no_bridges', False)
- settings.set('tor_bridges_use_obfs4', False)
- settings.set('tor_bridges_use_meek_lite_amazon', True)
settings.set('tor_bridges_use_meek_lite_azure', False)
settings.set('tor_bridges_use_custom_bridges', '')
if self.tor_bridges_use_meek_lite_azure_radio.isChecked():
settings.set('no_bridges', False)
settings.set('tor_bridges_use_obfs4', False)
- settings.set('tor_bridges_use_meek_lite_amazon', False)
settings.set('tor_bridges_use_meek_lite_azure', True)
settings.set('tor_bridges_use_custom_bridges', '')
if self.tor_bridges_use_custom_radio.isChecked():
settings.set('no_bridges', False)
settings.set('tor_bridges_use_obfs4', False)
- settings.set('tor_bridges_use_meek_lite_amazon', False)
settings.set('tor_bridges_use_meek_lite_azure', False)
# Insert a 'Bridge' line at the start of each bridge.
@@ -835,10 +1032,8 @@ class SettingsDialog(QtWidgets.QDialog):
ipv6_pattern = re.compile("(obfs4\s+)?\[(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\]:[0-9]+\s+[A-Z0-9]+(.+)$")
meek_lite_pattern = re.compile("(meek_lite)(\s)+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+)(\s)+([0-9A-Z]+)(\s)+url=(.+)(\s)+front=(.+)")
if ipv4_pattern.match(bridge) or \
- ipv6_pattern.match(bridge):
- new_bridges.append(''.join(['Bridge ', bridge, '\n']))
- bridges_valid = True
- if self.system != 'Windows' and self.system != 'Darwin' and meek_lite_pattern.match(bridge):
+ ipv6_pattern.match(bridge) or \
+ meek_lite_pattern.match(bridge):
new_bridges.append(''.join(['Bridge ', bridge, '\n']))
bridges_valid = True
@@ -846,41 +1041,42 @@ class SettingsDialog(QtWidgets.QDialog):
new_bridges = ''.join(new_bridges)
settings.set('tor_bridges_use_custom_bridges', new_bridges)
else:
- Alert(strings._('gui_settings_tor_bridges_invalid', True))
+ Alert(self.common, strings._('gui_settings_tor_bridges_invalid'))
settings.set('no_bridges', True)
return False
return settings
def closeEvent(self, e):
- common.log('SettingsDialog', 'closeEvent')
+ self.common.log('SettingsDialog', 'closeEvent')
# On close, if Tor isn't connected, then quit OnionShare altogether
- if not self.onion.is_authenticated():
- 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):
- common.log('SettingsDialog', '_update_autoupdate_timestamp')
+ self.common.log('SettingsDialog', '_update_autoupdate_timestamp')
if autoupdate_timestamp:
dt = datetime.datetime.fromtimestamp(autoupdate_timestamp)
last_checked = dt.strftime('%B %d, %Y %H:%M')
else:
- last_checked = strings._('gui_settings_autoupdate_timestamp_never', True)
- self.autoupdate_timestamp.setText(strings._('gui_settings_autoupdate_timestamp', True).format(last_checked))
+ last_checked = strings._('gui_settings_autoupdate_timestamp_never')
+ self.autoupdate_timestamp.setText(strings._('gui_settings_autoupdate_timestamp').format(last_checked))
def _tor_status_update(self, progress, summary):
- self.tor_status.setText('<strong>{}</strong><br>{}% {}'.format(strings._('connecting_to_tor', True), progress, summary))
+ self.tor_status.setText('<strong>{}</strong><br>{}% {}'.format(strings._('connecting_to_tor'), progress, summary))
self.qtapp.processEvents()
if 'Done' in summary:
self.tor_status.hide()
self._enable_buttons()
def _disable_buttons(self):
- common.log('SettingsDialog', '_disable_buttons')
+ self.common.log('SettingsDialog', '_disable_buttons')
self.check_for_updates_button.setEnabled(False)
self.connection_type_test_button.setEnabled(False)
@@ -888,7 +1084,7 @@ class SettingsDialog(QtWidgets.QDialog):
self.cancel_button.setEnabled(False)
def _enable_buttons(self):
- common.log('SettingsDialog', '_enable_buttons')
+ self.common.log('SettingsDialog', '_enable_buttons')
# We can't check for updates if we're still not connected to Tor
if not self.onion.connected_to_tor:
self.check_for_updates_button.setEnabled(False)