mirror of
https://github.com/onionshare/onionshare.git
synced 2025-01-10 03:37:28 -03:00
Make automatic detection flip through country names while it's running meek
This commit is contained in:
parent
feaecc9e4d
commit
8416d089f4
7 changed files with 96 additions and 217 deletions
|
@ -115,7 +115,6 @@ class Settings(object):
|
|||
"persistent_tabs": [],
|
||||
"locale": None, # this gets defined in fill_in_defaults()
|
||||
"theme": 0,
|
||||
"censorship_circumvention": False,
|
||||
}
|
||||
self._settings = {}
|
||||
self.fill_in_defaults()
|
||||
|
|
|
@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
from PySide2 import QtCore, QtWidgets, QtGui
|
||||
|
||||
from onionshare_cli.settings import Settings
|
||||
|
@ -75,13 +76,15 @@ class AutoConnectTab(QtWidgets.QWidget):
|
|||
# First launch widget
|
||||
self.first_launch_widget = AutoConnectFirstLaunchWidget(self.common)
|
||||
self.first_launch_widget.toggle_auto_connect.connect(self.toggle_auto_connect)
|
||||
self.first_launch_widget.connect_clicked.connect(self.connect_clicked)
|
||||
self.first_launch_widget.connect_clicked.connect(
|
||||
self.first_launch_widget_connect_clicked
|
||||
)
|
||||
self.first_launch_widget.open_tor_settings.connect(self.open_tor_settings)
|
||||
self.first_launch_widget.show()
|
||||
|
||||
# Use bridge widget
|
||||
self.use_bridge_widget = AutoConnectUseBridgeWidget(self.common)
|
||||
self.use_bridge_widget.connect_clicked.connect(self.connect_clicked)
|
||||
self.use_bridge_widget.connect_clicked.connect(self.use_bridge_connect_clicked)
|
||||
self.use_bridge_widget.back_clicked.connect(self.back_clicked)
|
||||
self.use_bridge_widget.open_tor_settings.connect(self.open_tor_settings)
|
||||
self.use_bridge_widget.hide()
|
||||
|
@ -119,7 +122,7 @@ class AutoConnectTab(QtWidgets.QWidget):
|
|||
self.first_launch_widget.enable_autoconnect_checkbox.setCheckState(
|
||||
QtCore.Qt.Checked
|
||||
)
|
||||
self.connect_clicked()
|
||||
self.first_launch_widget_connect_clicked()
|
||||
|
||||
def toggle_auto_connect(self):
|
||||
"""
|
||||
|
@ -135,17 +138,12 @@ class AutoConnectTab(QtWidgets.QWidget):
|
|||
def open_tor_settings(self):
|
||||
self.parent.open_tor_settings_tab()
|
||||
|
||||
def connect_clicked(self):
|
||||
def first_launch_widget_connect_clicked(self):
|
||||
"""
|
||||
Connect button clicked. Try to connect to tor.
|
||||
Connect button in first launch widget clicked. Try to connect to tor.
|
||||
"""
|
||||
self.common.log("AutoConnectTab", "connect_clicked")
|
||||
|
||||
# Hide the buttons
|
||||
if self.first_launch_widget.isVisible():
|
||||
self.first_launch_widget.hide_buttons()
|
||||
elif self.use_bridge_widget.isVisible():
|
||||
self.use_bridge_widget.hide_buttons()
|
||||
self.common.log("AutoConnectTab", "first_launch_widget_connect_clicked")
|
||||
self.first_launch_widget.hide_buttons()
|
||||
|
||||
if not self.common.gui.local_only:
|
||||
self.tor_con.show()
|
||||
|
@ -153,6 +151,33 @@ class AutoConnectTab(QtWidgets.QWidget):
|
|||
else:
|
||||
self.close_this_tab.emit()
|
||||
|
||||
def use_bridge_connect_clicked(self):
|
||||
"""
|
||||
Connect button in use bridge widget clicked.
|
||||
"""
|
||||
self.common.log(
|
||||
"AutoConnectTab",
|
||||
"use_bridge_connect_clicked",
|
||||
"Trying to automatically obtain bridges",
|
||||
)
|
||||
self.use_bridge_widget.hide_buttons()
|
||||
self.use_bridge_widget.start_autodetecting_location()
|
||||
|
||||
# self.common.gui.meek.start()
|
||||
# self.censorship_circumvention = CensorshipCircumvention(
|
||||
# self.common, self.common.gui.meek
|
||||
# )
|
||||
# bridge_settings = self.censorship_circumvention.request_settings(country="tm")
|
||||
# self.common.gui.meek.cleanup()
|
||||
|
||||
# if bridge_settings and self.censorship_circumvention.save_settings(
|
||||
# self.settings, bridge_settings
|
||||
# ):
|
||||
# # Try and connect again
|
||||
# self.start()
|
||||
# else:
|
||||
# self.fail.emit()
|
||||
|
||||
def back_clicked(self):
|
||||
"""
|
||||
Switch from use bridge widget back to first launch widget
|
||||
|
@ -174,7 +199,7 @@ class AutoConnectTab(QtWidgets.QWidget):
|
|||
# Close the tab
|
||||
self.close_this_tab.emit()
|
||||
|
||||
def tor_con_fail(self, msg):
|
||||
def tor_con_fail(self):
|
||||
"""
|
||||
Finished testing tor connection.
|
||||
"""
|
||||
|
@ -312,6 +337,11 @@ class AutoConnectUseBridgeWidget(QtWidgets.QWidget):
|
|||
for country_code in countries:
|
||||
self.country_combobox.addItem(countries[country_code], country_code)
|
||||
|
||||
# Task label
|
||||
self.task_label = QtWidgets.QLabel()
|
||||
self.task_label.setStyleSheet(common.gui.css["enable_autoconnect"])
|
||||
self.task_label.hide()
|
||||
|
||||
# Buttons
|
||||
self.connect_button = QtWidgets.QPushButton(
|
||||
strings._("gui_autoconnect_bridge_start")
|
||||
|
@ -346,6 +376,7 @@ class AutoConnectUseBridgeWidget(QtWidgets.QWidget):
|
|||
layout.addWidget(description_label)
|
||||
layout.addLayout(detect_layout)
|
||||
layout.addWidget(self.country_combobox)
|
||||
layout.addWidget(self.task_label)
|
||||
layout.addWidget(cta_widget)
|
||||
self.setLayout(layout)
|
||||
|
||||
|
@ -353,12 +384,39 @@ class AutoConnectUseBridgeWidget(QtWidgets.QWidget):
|
|||
|
||||
def hide_buttons(self):
|
||||
self.connect_button.hide()
|
||||
self.back_button.hide()
|
||||
self.configure_button.hide()
|
||||
|
||||
def show_buttons(self):
|
||||
self.connect_button.show()
|
||||
self.back_button.show()
|
||||
self.configure_button.show()
|
||||
|
||||
def start_autodetecting_location(self):
|
||||
self.detect_automatic_radio.setEnabled(False)
|
||||
self.detect_manual_radio.setEnabled(False)
|
||||
|
||||
self.country_combobox.setEnabled(False)
|
||||
self.country_combobox.show()
|
||||
|
||||
# If we're automatically detecting it, randomly switch up the country
|
||||
# dropdown until we detect the location
|
||||
if self.detect_automatic_radio.isChecked():
|
||||
self.task_label.show()
|
||||
self.task_label.setText(strings._("gui_autoconnect_task_detect_location"))
|
||||
|
||||
self.autodetecting_timer = QtCore.QTimer()
|
||||
self.autodetecting_timer.timeout.connect(self._autodetecting_timer_callback)
|
||||
self.autodetecting_timer.start(200)
|
||||
|
||||
def stop_autodetecting_location(self):
|
||||
self.task_label.hide()
|
||||
self.autodetecting_timer.stop()
|
||||
|
||||
def _autodetecting_timer_callback(self):
|
||||
new_index = random.randrange(0, self.country_combobox.count())
|
||||
self.country_combobox.setCurrentIndex(new_index)
|
||||
|
||||
def _detect_automatic_toggled(self):
|
||||
self.country_combobox.setEnabled(False)
|
||||
self.country_combobox.hide()
|
||||
|
|
|
@ -40,6 +40,7 @@ from onionshare_cli.onion import (
|
|||
TorTooOldStealth,
|
||||
PortNotAvailable,
|
||||
)
|
||||
from onionshare_cli.meek import Meek
|
||||
|
||||
|
||||
class GuiCommon:
|
||||
|
@ -78,6 +79,9 @@ class GuiCommon:
|
|||
os.makedirs(self.events_dir, 0o700, True)
|
||||
self.events_filename = os.path.join(self.events_dir, "events")
|
||||
|
||||
# Instantiate Meek, which is used to bypass censorship
|
||||
self.meek = Meek(self.common, get_tor_paths=self.get_tor_paths)
|
||||
|
||||
self.css = self.get_css(qtapp.color_mode)
|
||||
self.color_mode = qtapp.color_mode
|
||||
|
||||
|
@ -185,6 +189,11 @@ class GuiCommon:
|
|||
color: #666666;
|
||||
}
|
||||
""",
|
||||
"autoconnect_task_label": """
|
||||
QLabel {
|
||||
font-weight: bold;
|
||||
}
|
||||
""",
|
||||
# Common styles between modes and their child widgets
|
||||
"mode_settings_toggle_advanced": """
|
||||
QPushButton {
|
||||
|
|
|
@ -26,10 +26,10 @@ from . import strings
|
|||
from .widgets import Alert
|
||||
from .update_checker import UpdateThread
|
||||
from .tab_widget import TabWidget
|
||||
from .settings_tab import SettingsTab
|
||||
from .gui_common import GuiCommon
|
||||
from .threads import OnionCleanupThread
|
||||
|
||||
from onionshare_cli.meek import Meek
|
||||
|
||||
class MainWindow(QtWidgets.QMainWindow):
|
||||
"""
|
||||
|
@ -53,7 +53,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
self.settings_action = menu.addAction(strings._("gui_settings_window_title"))
|
||||
self.settings_action.triggered.connect(self.open_settings)
|
||||
self.help_action = menu.addAction(strings._("gui_settings_button_help"))
|
||||
self.help_action.triggered.connect(lambda: SettingsDialog.help_clicked(self))
|
||||
self.help_action.triggered.connect(lambda: SettingsTab.open_help())
|
||||
exit_action = menu.addAction(strings._("systray_menu_exit"))
|
||||
exit_action.triggered.connect(self.close)
|
||||
|
||||
|
@ -160,23 +160,6 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||
self.setCentralWidget(central_widget)
|
||||
self.show()
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
# Instantiate Meek, which the TorConnectionDialog may use to resolve
|
||||
# connection issues by automatically obtaining bridges.
|
||||
self.meek = Meek(self.common, get_tor_paths=self.common.gui.get_tor_paths)
|
||||
# Start the "Connecting to Tor" dialog, which calls onion.connect()
|
||||
tor_con = TorConnectionDialog(self.common, self.meek)
|
||||
tor_con.canceled.connect(self.tor_connection_canceled)
|
||||
tor_con.open_tor_settings.connect(self.tor_connection_open_tor_settings)
|
||||
if not self.common.gui.local_only:
|
||||
tor_con.start()
|
||||
self.settings_have_changed()
|
||||
|
||||
# After connecting to Tor, check for updates
|
||||
self.check_for_updates()
|
||||
|
||||
>>>>>>> mig5-censorship_automatically_attempt_and_reconnect
|
||||
# Create the close warning dialog -- the dialog widget needs to be in the constructor
|
||||
# in order to test it
|
||||
self.close_dialog = QtWidgets.QMessageBox()
|
||||
|
|
|
@ -45,12 +45,13 @@
|
|||
"gui_autoconnect_description": "OnionShare relies on the Tor Network, run by thousands of volunteers around the world.",
|
||||
"gui_enable_autoconnect_checkbox": "Enable automatically connecting to Tor",
|
||||
"gui_autoconnect_bridge_description": "<b>Failed connecting to Tor.</b> This could be because your internet is being censored. You might be able to bypass this censorship by using a bridge.",
|
||||
"gui_autoconnect_bridge_detect_automatic": "Automatically determine my location to bypass country-specific censorship",
|
||||
"gui_autoconnect_bridge_detect_automatic": "Automatically determine my country to bypass country-specific censorship",
|
||||
"gui_autoconnect_bridge_detect_manual": "Manually select my country",
|
||||
"gui_autoconnect_start": "Connect to Tor",
|
||||
"gui_autoconnect_configure": "Network Settings",
|
||||
"gui_autoconnect_bridge_start": "Use a Bridge",
|
||||
"gui_autoconnect_bridge_back": "Back",
|
||||
"gui_autoconnect_task_detect_location": "Automatically determining your country...",
|
||||
"gui_settings_window_title": "Settings",
|
||||
"gui_settings_autoupdate_label": "Check for new version",
|
||||
"gui_settings_autoupdate_option": "Notify me when a new version is available",
|
||||
|
@ -243,4 +244,4 @@
|
|||
"moat_captcha_error": "The solution is not correct. Please try again.",
|
||||
"moat_solution_empty_error": "You must enter the characters from the image",
|
||||
"mode_tor_not_connected_label": "OnionShare is not connected to the Tor network"
|
||||
}
|
||||
}
|
|
@ -168,7 +168,7 @@ class TabWidget(QtWidgets.QTabWidget):
|
|||
self.add_tab()
|
||||
else:
|
||||
self.open_connection_tab()
|
||||
|
||||
|
||||
def check_autoconnect_tab(self):
|
||||
if type(self.tabs[0]) is AutoConnectTab:
|
||||
self.tabs[0].check_autoconnect()
|
||||
|
@ -218,7 +218,9 @@ class TabWidget(QtWidgets.QTabWidget):
|
|||
self.setCurrentIndex(self.indexOf(self.tabs[tab_id]))
|
||||
return
|
||||
|
||||
connection_tab = AutoConnectTab(self.common, self.current_tab_id, self.status_bar, parent=self)
|
||||
connection_tab = AutoConnectTab(
|
||||
self.common, self.current_tab_id, self.status_bar, parent=self
|
||||
)
|
||||
connection_tab.close_this_tab.connect(self.close_connection_tab)
|
||||
self.tabs[self.current_tab_id] = connection_tab
|
||||
self.current_tab_id += 1
|
||||
|
|
|
@ -39,153 +39,9 @@ from onionshare_cli.onion import (
|
|||
)
|
||||
|
||||
from . import strings
|
||||
from .gui_common import GuiCommon
|
||||
from .widgets import Alert
|
||||
from onionshare_cli.censorship import CensorshipCircumvention
|
||||
|
||||
|
||||
class TorConnectionDialog(QtWidgets.QProgressDialog):
|
||||
"""
|
||||
Connecting to Tor dialog.
|
||||
"""
|
||||
|
||||
open_tor_settings = QtCore.Signal()
|
||||
success = QtCore.Signal()
|
||||
|
||||
def __init__(
|
||||
self, common, meek, custom_settings=False, testing_settings=False, onion=None
|
||||
):
|
||||
super(TorConnectionDialog, self).__init__(None)
|
||||
|
||||
self.common = common
|
||||
self.testing_settings = testing_settings
|
||||
|
||||
self.meek = meek
|
||||
|
||||
if custom_settings:
|
||||
self.settings = custom_settings
|
||||
else:
|
||||
self.settings = self.common.settings
|
||||
|
||||
self.common.log("TorConnectionDialog", "__init__")
|
||||
|
||||
if self.testing_settings:
|
||||
self.title = strings._("gui_settings_connection_type_test_button")
|
||||
self.onion = onion
|
||||
else:
|
||||
self.title = "OnionShare"
|
||||
self.onion = self.common.gui.onion
|
||||
|
||||
self.setWindowTitle(self.title)
|
||||
|
||||
self.setWindowIcon(QtGui.QIcon(GuiCommon.get_resource_path("images/logo.png")))
|
||||
self.setModal(True)
|
||||
self.setFixedSize(400, 150)
|
||||
|
||||
# Label
|
||||
self.setLabelText(strings._("connecting_to_tor"))
|
||||
|
||||
# Progress bar ticks from 0 to 100
|
||||
self.setRange(0, 100)
|
||||
# Don't show if connection takes less than 100ms (for non-bundled tor)
|
||||
self.setMinimumDuration(100)
|
||||
|
||||
# Start displaying the status at 0
|
||||
self._tor_status_update(0, "")
|
||||
|
||||
def start(self):
|
||||
self.common.log("TorConnectionDialog", "start")
|
||||
|
||||
t = TorConnectionThread(self.common, self.settings, self)
|
||||
t.tor_status_update.connect(self._tor_status_update)
|
||||
t.connected_to_tor.connect(self._connected_to_tor)
|
||||
t.canceled_connecting_to_tor.connect(self._canceled_connecting_to_tor)
|
||||
t.error_connecting_to_tor.connect(self._error_connecting_to_tor)
|
||||
t.start()
|
||||
|
||||
# The main thread needs to remain active, and checking for Qt events,
|
||||
# until the thread is finished. Otherwise it won't be able to handle
|
||||
# accepting signals.
|
||||
self.active = True
|
||||
while self.active:
|
||||
time.sleep(0.1)
|
||||
self.common.gui.qtapp.processEvents()
|
||||
|
||||
def _tor_status_update(self, progress, summary):
|
||||
self.setValue(int(progress))
|
||||
self.setLabelText(
|
||||
f"<strong>{strings._('connecting_to_tor')}</strong><br>{summary}"
|
||||
)
|
||||
|
||||
def _connected_to_tor(self):
|
||||
self.common.log("TorConnectionDialog", "_connected_to_tor")
|
||||
self.active = False
|
||||
# Close the dialog after connecting
|
||||
self.setValue(self.maximum())
|
||||
|
||||
def _canceled_connecting_to_tor(self):
|
||||
self.common.log("TorConnectionDialog", "_canceled_connecting_to_tor")
|
||||
self.active = False
|
||||
self.onion.cleanup()
|
||||
|
||||
# Cancel connecting to Tor
|
||||
QtCore.QTimer.singleShot(1, self.cancel)
|
||||
|
||||
def _error_connecting_to_tor(self, msg):
|
||||
self.common.log("TorConnectionDialog", "_error_connecting_to_tor")
|
||||
self.active = False
|
||||
|
||||
if self.testing_settings:
|
||||
# If testing, just display the error but don't open settings
|
||||
def alert():
|
||||
Alert(self.common, msg, QtWidgets.QMessageBox.Warning, title=self.title)
|
||||
|
||||
# If we are allowed to try automatically resolving connection issues
|
||||
# (e.g possible censorship) by obtaining bridges for the user, do so
|
||||
elif self.settings.get("censorship_circumvention"):
|
||||
|
||||
def alert():
|
||||
return
|
||||
|
||||
# Automatically try to obtain bridges from the Censorship Circumvention API
|
||||
self.common.log(
|
||||
"TorConnectionDialog",
|
||||
"_error_connecting_to_tor",
|
||||
"Trying to automatically obtain bridges",
|
||||
)
|
||||
self.meek.start()
|
||||
self.censorship_circumvention = CensorshipCircumvention(
|
||||
self.common, self.meek
|
||||
)
|
||||
bridge_settings = self.censorship_circumvention.request_settings(
|
||||
country="tm"
|
||||
)
|
||||
self.meek.cleanup()
|
||||
|
||||
if bridge_settings and self.censorship_circumvention.save_settings(
|
||||
self.settings, bridge_settings
|
||||
):
|
||||
# Try and connect again
|
||||
self.start()
|
||||
else:
|
||||
# If not testing, open settings after displaying the error
|
||||
def alert():
|
||||
Alert(
|
||||
self.common,
|
||||
f"{msg}\n\n{strings._('gui_tor_connection_error_settings')}",
|
||||
QtWidgets.QMessageBox.Warning,
|
||||
title=self.title,
|
||||
)
|
||||
|
||||
# Open settings
|
||||
self.open_tor_settings.emit()
|
||||
|
||||
QtCore.QTimer.singleShot(1, alert)
|
||||
|
||||
# Cancel connecting to Tor
|
||||
QtCore.QTimer.singleShot(1, self.cancel)
|
||||
|
||||
|
||||
class TorConnectionWidget(QtWidgets.QWidget):
|
||||
"""
|
||||
Connecting to Tor widget, with a progress bar
|
||||
|
@ -193,9 +49,9 @@ class TorConnectionWidget(QtWidgets.QWidget):
|
|||
|
||||
open_tor_settings = QtCore.Signal()
|
||||
success = QtCore.Signal()
|
||||
fail = QtCore.Signal(str)
|
||||
fail = QtCore.Signal()
|
||||
|
||||
def __init__(self, common, status_bar, meek):
|
||||
def __init__(self, common, status_bar):
|
||||
super(TorConnectionWidget, self).__init__(None)
|
||||
self.common = common
|
||||
self.common.log("TorConnectionWidget", "__init__")
|
||||
|
@ -211,8 +67,6 @@ class TorConnectionWidget(QtWidgets.QWidget):
|
|||
)
|
||||
self.cancel_button.clicked.connect(self.cancel_clicked)
|
||||
|
||||
self.meek = meek
|
||||
|
||||
progress_layout = QtWidgets.QHBoxLayout()
|
||||
progress_layout.addWidget(self.progress)
|
||||
progress_layout.addWidget(self.cancel_button)
|
||||
|
@ -259,7 +113,7 @@ class TorConnectionWidget(QtWidgets.QWidget):
|
|||
|
||||
def cancel_clicked(self):
|
||||
self.was_canceled = True
|
||||
self.fail.emit("")
|
||||
self.fail.emit()
|
||||
|
||||
def wasCanceled(self):
|
||||
return self.was_canceled
|
||||
|
@ -288,44 +142,17 @@ class TorConnectionWidget(QtWidgets.QWidget):
|
|||
# Cancel connecting to Tor
|
||||
QtCore.QTimer.singleShot(1, self.cancel_clicked)
|
||||
|
||||
def _error_connecting_to_tor(self, msg):
|
||||
def _error_connecting_to_tor(self):
|
||||
self.common.log("TorConnectionWidget", "_error_connecting_to_tor")
|
||||
self.active = False
|
||||
|
||||
# If we are allowed to try automatically resolving connection issues
|
||||
# (e.g possible censorship) by obtaining bridges for the user, do so
|
||||
if self.settings.get("censorship_circumvention"):
|
||||
# Automatically try to obtain bridges from the Censorship Circumvention API
|
||||
self.common.log(
|
||||
"TorConnectionWidget",
|
||||
"_error_connecting_to_tor",
|
||||
"Trying to automatically obtain bridges",
|
||||
)
|
||||
self.meek.start()
|
||||
self.censorship_circumvention = CensorshipCircumvention(
|
||||
self.common, self.meek
|
||||
)
|
||||
bridge_settings = self.censorship_circumvention.request_settings(
|
||||
country="tm"
|
||||
)
|
||||
self.meek.cleanup()
|
||||
|
||||
if bridge_settings and self.censorship_circumvention.save_settings(
|
||||
self.settings, bridge_settings
|
||||
):
|
||||
# Try and connect again
|
||||
self.start()
|
||||
else:
|
||||
self.fail.emit()
|
||||
else:
|
||||
self.fail.emit()
|
||||
self.fail.emit()
|
||||
|
||||
|
||||
class TorConnectionThread(QtCore.QThread):
|
||||
tor_status_update = QtCore.Signal(str, str)
|
||||
connected_to_tor = QtCore.Signal()
|
||||
canceled_connecting_to_tor = QtCore.Signal()
|
||||
error_connecting_to_tor = QtCore.Signal(str)
|
||||
error_connecting_to_tor = QtCore.Signal()
|
||||
|
||||
def __init__(self, common, settings, parent):
|
||||
super(TorConnectionThread, self).__init__()
|
||||
|
@ -370,7 +197,7 @@ class TorConnectionThread(QtCore.QThread):
|
|||
self.common.log(
|
||||
"TorConnectionThread", "run", f"caught exception: {message}"
|
||||
)
|
||||
self.error_connecting_to_tor.emit(message)
|
||||
self.error_connecting_to_tor.emit()
|
||||
|
||||
def _tor_status_update(self, progress, summary):
|
||||
self.tor_status_update.emit(progress, summary)
|
||||
|
|
Loading…
Reference in a new issue