aboutsummaryrefslogtreecommitdiff
path: root/desktop/onionshare/gui_common.py
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/onionshare/gui_common.py')
-rw-r--r--desktop/onionshare/gui_common.py510
1 files changed, 510 insertions, 0 deletions
diff --git a/desktop/onionshare/gui_common.py b/desktop/onionshare/gui_common.py
new file mode 100644
index 00000000..2a0bae4d
--- /dev/null
+++ b/desktop/onionshare/gui_common.py
@@ -0,0 +1,510 @@
+# -*- coding: utf-8 -*-
+"""
+OnionShare | https://onionshare.org/
+
+Copyright (C) 2014-2021 Micah Lee, et al. <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
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+
+import os
+import shutil
+from pkg_resources import resource_filename
+
+from . import strings
+from onionshare_cli.onion import (
+ Onion,
+ TorErrorInvalidSetting,
+ TorErrorAutomatic,
+ TorErrorSocketPort,
+ TorErrorSocketFile,
+ TorErrorMissingPassword,
+ TorErrorUnreadableCookieFile,
+ TorErrorAuthError,
+ TorErrorProtocolError,
+ BundledTorTimeout,
+ BundledTorBroken,
+ TorTooOldEphemeral,
+ TorTooOldStealth,
+ PortNotAvailable,
+)
+
+
+class GuiCommon:
+ """
+ The shared code for all of the OnionShare GUI.
+ """
+
+ MODE_SHARE = "share"
+ MODE_RECEIVE = "receive"
+ MODE_WEBSITE = "website"
+ MODE_CHAT = "chat"
+
+ def __init__(self, common, qtapp, local_only):
+ self.common = common
+ self.qtapp = qtapp
+ self.local_only = local_only
+
+ # Are we running in a flatpak package?
+ self.is_flatpak = os.path.exists("/.flatpak-info")
+
+ # Load settings
+ self.common.load_settings()
+
+ # Load strings
+ strings.load_strings(self.common, self.get_resource_path("locale"))
+
+ # Start the Onion
+ self.onion = Onion(common, get_tor_paths=self.get_tor_paths)
+
+ # Lock filename
+ self.lock_filename = os.path.join(self.common.build_data_dir(), "lock")
+
+ # Events filenames
+ self.events_dir = os.path.join(self.common.build_data_dir(), "events")
+ if not os.path.exists(self.events_dir):
+ os.makedirs(self.events_dir, 0o700, True)
+ self.events_filename = os.path.join(self.events_dir, "events")
+
+ self.css = self.get_css(qtapp.color_mode)
+ self.color_mode = qtapp.color_mode
+
+ def get_css(self, color_mode):
+ header_color = "#4E064F" # purple in light
+ title_color = "#333333" # dark gray color in main window
+ stop_button_color = "#d0011b" # red button color for stopping server
+ new_tab_button_background = "#ffffff"
+ new_tab_button_border = "#efeff0"
+ new_tab_button_text_color = "#4e0d4e"
+ downloads_uploads_progress_bar_border_color = "#4E064F"
+ downloads_uploads_progress_bar_chunk_color = "#4E064F"
+ share_zip_progess_bar_border_color = "#4E064F"
+ share_zip_progess_bar_chunk_color = "#4E064F"
+ history_background_color = "#ffffff"
+ history_label_color = "#000000"
+ settings_error_color = "#FF0000"
+ if color_mode == "dark":
+ header_color = "#F2F2F2"
+ title_color = "#F2F2F2"
+ stop_button_color = "#C32F2F"
+ new_tab_button_background = "#5F5F5F"
+ new_tab_button_border = "#878787"
+ new_tab_button_text_color = "#FFFFFF"
+ share_zip_progess_bar_border_color = "#F2F2F2"
+ history_background_color = "#191919"
+ history_label_color = "#ffffff"
+ settings_error_color = "#FF9999"
+
+ return {
+ # OnionShareGui styles
+ "tab_widget": """
+ QTabBar::tab { width: 170px; height: 30px; }
+ """,
+ "tab_widget_new_tab_button": """
+ QPushButton {
+ font-weight: bold;
+ font-size: 20px;
+ }""",
+ "mode_new_tab_button": """
+ QPushButton {
+ font-weight: bold;
+ font-size: 30px;
+ color: #601f61;
+ }""",
+ "mode_header_label": """
+ QLabel {
+ color: """
+ + header_color
+ + """;
+ font-size: 48px;
+ margin-bottom: 16px;
+ }""",
+ "settings_button": """
+ QPushButton {
+ border: 0;
+ border-radius: 0;
+ }""",
+ "server_status_indicator_label": """
+ QLabel {
+ font-style: italic;
+ color: #666666;
+ padding: 2px;
+ }""",
+ "status_bar": """
+ QStatusBar {
+ font-style: italic;
+ color: #666666;
+ }
+ QStatusBar::item {
+ border: 0px;
+ }""",
+ # Common styles between modes and their child widgets
+ "mode_settings_toggle_advanced": """
+ QPushButton {
+ color: #3f7fcf;
+ text-align: left;
+ }
+ """,
+ "mode_info_label": """
+ QLabel {
+ font-size: 12px;
+ color: #666666;
+ }
+ """,
+ "server_status_url": """
+ QLabel {
+ background-color: #ffffff;
+ color: #000000;
+ padding: 10px;
+ border: 1px solid #666666;
+ font-size: 12px;
+ }
+ """,
+ "server_status_url_buttons": """
+ QPushButton {
+ padding: 4px 8px;
+ text-align: center;
+ }
+ """,
+ "server_status_button_stopped": """
+ QPushButton {
+ background-color: #5fa416;
+ color: #ffffff;
+ padding: 10px 30px 10px 30px;
+ border: 0;
+ border-radius: 5px;
+ }""",
+ "server_status_button_working": """
+ QPushButton {
+ background-color: #4c8211;
+ color: #ffffff;
+ padding: 10px 30px 10px 30px;
+ border: 0;
+ border-radius: 5px;
+ font-style: italic;
+ }""",
+ "server_status_button_started": """
+ QPushButton {
+ background-color: """
+ + stop_button_color
+ + """;
+ color: #ffffff;
+ padding: 10px 30px 10px 30px;
+ border: 0;
+ border-radius: 5px;
+ }""",
+ "downloads_uploads_not_empty": """
+ QWidget{
+ background-color: """
+ + history_background_color
+ + """;
+ }""",
+ "downloads_uploads_empty": """
+ QWidget {
+ background-color: """
+ + history_background_color
+ + """;
+ border: 1px solid #999999;
+ }
+ QWidget QLabel {
+ background-color: none;
+ border: 0px;
+ }
+ """,
+ "downloads_uploads_empty_text": """
+ QLabel {
+ color: #999999;
+ }""",
+ "downloads_uploads_label": """
+ QLabel {
+ font-weight: bold;
+ font-size 14px;
+ text-align: center;
+ background-color: none;
+ border: none;
+ }""",
+ "downloads_uploads_clear": """
+ QPushButton {
+ color: #3f7fcf;
+ }
+ """,
+ "download_uploads_indicator": """
+ QLabel {
+ color: #ffffff;
+ background-color: #f44449;
+ font-weight: bold;
+ font-size: 10px;
+ padding: 2px;
+ border-radius: 7px;
+ text-align: center;
+ }""",
+ "downloads_uploads_progress_bar": """
+ QProgressBar {
+ border: 1px solid """
+ + downloads_uploads_progress_bar_border_color
+ + """;
+ background-color: #ffffff !important;
+ text-align: center;
+ color: #9b9b9b;
+ font-size: 14px;
+ }
+ QProgressBar::chunk {
+ background-color: """
+ + downloads_uploads_progress_bar_chunk_color
+ + """;
+ width: 10px;
+ }""",
+ "history_default_label": """
+ QLabel {
+ color: """
+ + history_label_color
+ + """;
+ }""",
+ "history_individual_file_timestamp_label": """
+ QLabel {
+ color: #666666;
+ }""",
+ "history_individual_file_status_code_label_2xx": """
+ QLabel {
+ color: #008800;
+ }""",
+ "history_individual_file_status_code_label_4xx": """
+ QLabel {
+ color: #cc0000;
+ }""",
+ "tor_not_connected_label": """
+ QLabel {
+ font-size: 16px;
+ font-style: italic;
+ }""",
+ # New tab
+ "new_tab_button_image": """
+ QLabel {
+ padding: 30px;
+ text-align: center;
+ }
+ """,
+ "new_tab_button_text": """
+ QLabel {
+ border: 1px solid """
+ + new_tab_button_border
+ + """;
+ border-radius: 4px;
+ background-color: """
+ + new_tab_button_background
+ + """;
+ text-align: center;
+ color: """
+ + new_tab_button_text_color
+ + """;
+ }
+ """,
+ "new_tab_title_text": """
+ QLabel {
+ text-align: center;
+ color: """
+ + title_color
+ + """;
+ font-size: 25px;
+ }
+ """,
+ # Share mode and child widget styles
+ "share_delete_all_files_button": """
+ QPushButton {
+ color: #3f7fcf;
+ }
+ """,
+ "share_zip_progess_bar": """
+ QProgressBar {
+ border: 1px solid """
+ + share_zip_progess_bar_border_color
+ + """;
+ background-color: #ffffff !important;
+ text-align: center;
+ color: #9b9b9b;
+ }
+ QProgressBar::chunk {
+ border: 0px;
+ background-color: """
+ + share_zip_progess_bar_chunk_color
+ + """;
+ width: 10px;
+ }""",
+ "share_filesize_warning": """
+ QLabel {
+ padding: 10px 0;
+ font-weight: bold;
+ color: """
+ + title_color
+ + """;
+ }
+ """,
+ "share_file_selection_drop_here_header_label": """
+ QLabel {
+ color: """
+ + header_color
+ + """;
+ font-size: 48px;
+ }""",
+ "share_file_selection_drop_here_label": """
+ QLabel {
+ color: #666666;
+ }""",
+ "share_file_selection_drop_count_label": """
+ QLabel {
+ color: #ffffff;
+ background-color: #f44449;
+ font-weight: bold;
+ padding: 5px 10px;
+ border-radius: 10px;
+ }""",
+ "share_file_list_drag_enter": """
+ FileList {
+ border: 3px solid #538ad0;
+ }
+ """,
+ "share_file_list_drag_leave": """
+ FileList {
+ border: none;
+ }
+ """,
+ "share_file_list_item_size": """
+ QLabel {
+ color: #666666;
+ font-size: 11px;
+ }""",
+ # Receive mode and child widget styles
+ "receive_file": """
+ QWidget {
+ background-color: #ffffff;
+ }
+ """,
+ "receive_file_size": """
+ QLabel {
+ color: #666666;
+ font-size: 11px;
+ }""",
+ "receive_message_button": """
+ QPushButton {
+ padding: 5px 10px;
+ }""",
+ # Tor Settings dialogs
+ "tor_settings_error": """
+ QLabel {
+ color: """
+ + settings_error_color
+ + """;
+ }
+ """,
+ }
+
+ def get_tor_paths(self):
+ if self.common.platform == "Linux":
+ base_path = self.get_resource_path("tor")
+ if base_path and os.path.isdir(base_path):
+ self.common.log(
+ "GuiCommon", "get_tor_paths", "using paths in resources"
+ )
+ tor_path = os.path.join(base_path, "tor")
+ tor_geo_ip_file_path = os.path.join(base_path, "geoip")
+ tor_geo_ipv6_file_path = os.path.join(base_path, "geoip6")
+ obfs4proxy_file_path = os.path.join(base_path, "obfs4proxy")
+ snowflake_file_path = os.path.join(base_path, "snowflake-client")
+ meek_client_file_path = os.path.join(base_path, "meek-client")
+ else:
+ # Fallback to looking in the path
+ self.common.log("GuiCommon", "get_tor_paths", "using paths from PATH")
+ tor_path = shutil.which("tor")
+ obfs4proxy_file_path = shutil.which("obfs4proxy")
+ snowflake_file_path = shutil.which("snowflake-client")
+ meek_client_file_path = shutil.which("meek-client")
+ prefix = os.path.dirname(os.path.dirname(tor_path))
+ tor_geo_ip_file_path = os.path.join(prefix, "share/tor/geoip")
+ tor_geo_ipv6_file_path = os.path.join(prefix, "share/tor/geoip6")
+
+ if self.common.platform == "Windows":
+ base_path = self.get_resource_path("tor")
+ tor_path = os.path.join(base_path, "Tor", "tor.exe")
+ obfs4proxy_file_path = os.path.join(base_path, "Tor", "obfs4proxy.exe")
+ snowflake_file_path = os.path.join(base_path, "Tor", "snowflake-client.exe")
+ meek_client_file_path = os.path.join(base_path, "Tor", "meek-client.exe")
+ tor_geo_ip_file_path = os.path.join(base_path, "Data", "Tor", "geoip")
+ tor_geo_ipv6_file_path = os.path.join(base_path, "Data", "Tor", "geoip6")
+ elif self.common.platform == "Darwin":
+ base_path = self.get_resource_path("tor")
+ tor_path = os.path.join(base_path, "tor")
+ obfs4proxy_file_path = os.path.join(base_path, "obfs4proxy")
+ snowflake_file_path = os.path.join(base_path, "snowflake-client")
+ meek_client_file_path = os.path.join(base_path, "meek-client")
+ tor_geo_ip_file_path = os.path.join(base_path, "geoip")
+ tor_geo_ipv6_file_path = os.path.join(base_path, "geoip6")
+ elif self.common.platform == "BSD":
+ tor_path = "/usr/local/bin/tor"
+ tor_geo_ip_file_path = "/usr/local/share/tor/geoip"
+ tor_geo_ipv6_file_path = "/usr/local/share/tor/geoip6"
+ obfs4proxy_file_path = "/usr/local/bin/obfs4proxy"
+ meek_client_file_path = "/usr/local/bin/meek-client"
+ snowflake_file_path = "/usr/local/bin/snowflake-client"
+
+ return (
+ tor_path,
+ tor_geo_ip_file_path,
+ tor_geo_ipv6_file_path,
+ obfs4proxy_file_path,
+ snowflake_file_path,
+ meek_client_file_path,
+ )
+
+ @staticmethod
+ def get_resource_path(filename):
+ """
+ Returns the absolute path of a resource
+ """
+ try:
+ return resource_filename("onionshare", os.path.join("resources", filename))
+ except KeyError:
+ return None
+
+ @staticmethod
+ def get_translated_tor_error(e):
+ """
+ Takes an exception defined in onion.py and returns a translated error message
+ """
+ if type(e) is TorErrorInvalidSetting:
+ return strings._("settings_error_unknown")
+ elif type(e) is TorErrorAutomatic:
+ return strings._("settings_error_automatic")
+ elif type(e) is TorErrorSocketPort:
+ return strings._("settings_error_socket_port").format(e.args[0], e.args[1])
+ elif type(e) is TorErrorSocketFile:
+ return strings._("settings_error_socket_file").format(e.args[0])
+ elif type(e) is TorErrorMissingPassword:
+ return strings._("settings_error_missing_password")
+ elif type(e) is TorErrorUnreadableCookieFile:
+ return strings._("settings_error_unreadable_cookie_file")
+ elif type(e) is TorErrorAuthError:
+ return strings._("settings_error_auth").format(e.args[0], e.args[1])
+ elif type(e) is TorErrorProtocolError:
+ return strings._("error_tor_protocol_error").format(e.args[0])
+ elif type(e) is BundledTorTimeout:
+ return strings._("settings_error_bundled_tor_timeout")
+ elif type(e) is BundledTorBroken:
+ return strings._("settings_error_bundled_tor_broken").format(e.args[0])
+ elif type(e) is TorTooOldEphemeral:
+ return strings._("error_ephemeral_not_supported")
+ elif type(e) is TorTooOldStealth:
+ return strings._("error_stealth_not_supported")
+ elif type(e) is PortNotAvailable:
+ return strings._("error_port_not_available")
+ return None