2016-12-28 22:52:21 -05:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
|
|
OnionShare | https://onionshare.org/
|
|
|
|
|
2022-01-16 19:15:49 -05:00
|
|
|
Copyright (C) 2014-2022 Micah Lee, et al. <micah@micahflee.com>
|
2016-12-28 22:52:21 -05:00
|
|
|
|
|
|
|
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/>.
|
|
|
|
"""
|
|
|
|
|
2017-07-10 22:13:30 -04:00
|
|
|
import json
|
|
|
|
import os
|
2018-09-30 17:45:21 -04:00
|
|
|
import locale
|
2018-12-19 14:45:31 -05:00
|
|
|
|
2017-07-10 22:13:30 -04:00
|
|
|
|
2016-12-28 22:52:21 -05:00
|
|
|
class Settings(object):
|
|
|
|
"""
|
|
|
|
This class stores all of the settings for OnionShare, specifically for how
|
|
|
|
to connect to Tor. If it can't find the settings file, it uses the default,
|
|
|
|
which is to attempt to connect automatically using default Tor Browser
|
|
|
|
settings.
|
|
|
|
"""
|
2019-10-13 00:01:25 -04:00
|
|
|
|
2018-03-08 13:18:31 -05:00
|
|
|
def __init__(self, common, config=False):
|
|
|
|
self.common = common
|
|
|
|
|
2019-10-13 00:01:25 -04:00
|
|
|
self.common.log("Settings", "__init__")
|
2017-05-16 14:23:18 -04:00
|
|
|
|
2017-06-01 03:35:27 -04:00
|
|
|
# If a readable config file was provided, use that instead
|
|
|
|
if config:
|
|
|
|
if os.path.isfile(config):
|
|
|
|
self.filename = config
|
|
|
|
else:
|
2019-10-13 00:01:25 -04:00
|
|
|
self.common.log(
|
|
|
|
"Settings",
|
|
|
|
"__init__",
|
|
|
|
"Supplied config does not exist or is unreadable. Falling back to default location",
|
|
|
|
)
|
2019-04-20 00:43:04 -04:00
|
|
|
self.filename = self.build_filename()
|
|
|
|
|
|
|
|
else:
|
|
|
|
# Default config
|
|
|
|
self.filename = self.build_filename()
|
2017-06-01 03:35:27 -04:00
|
|
|
|
2018-09-30 18:01:02 -04:00
|
|
|
# Dictionary of available languages in this version of OnionShare,
|
2018-09-30 19:18:40 -04:00
|
|
|
# mapped to the language name, in that language
|
2018-09-30 18:01:02 -04:00
|
|
|
self.available_locales = {
|
2022-01-17 13:33:13 -05:00
|
|
|
# "ar": "العربية", # Arabic
|
|
|
|
# "bn": "বাংলা", # Bengali
|
2021-09-26 14:41:01 -04:00
|
|
|
# "ca": "Català", # Catalan
|
|
|
|
# "zh_Hant": "正體中文 (繁體)", # Traditional Chinese
|
2019-10-13 00:01:25 -04:00
|
|
|
"zh_Hans": "中文 (简体)", # Simplified Chinese
|
2022-10-09 18:01:55 -04:00
|
|
|
"hr": "Hrvatski", # Croatian
|
|
|
|
"cs": "čeština", # Czech
|
2021-09-26 14:41:01 -04:00
|
|
|
# "da": "Dansk", # Danish
|
|
|
|
# "nl": "Nederlands", # Dutch
|
2019-10-13 00:01:25 -04:00
|
|
|
"en": "English", # English
|
2022-01-17 13:33:13 -05:00
|
|
|
# "fi": "Suomi", # Finnish
|
2022-10-09 18:01:55 -04:00
|
|
|
# "fr": "Français", # French
|
|
|
|
# "gl": "Galego", # Galician
|
2019-10-13 00:01:25 -04:00
|
|
|
"de": "Deutsch", # German
|
2022-01-17 13:33:13 -05:00
|
|
|
"el": "Ελληνικά", # Greek
|
2019-10-13 00:01:25 -04:00
|
|
|
"is": "Íslenska", # Icelandic
|
2021-09-26 14:41:01 -04:00
|
|
|
# "id": "Bahasa Indonesia", # Indonesian
|
2021-02-15 18:49:54 -05:00
|
|
|
# "ga": "Gaeilge", # Irish
|
2021-09-26 14:41:01 -04:00
|
|
|
# "it": "Italiano", # Italian
|
2022-01-17 13:33:13 -05:00
|
|
|
"ja": "日本語", # Japanese
|
2021-09-26 14:41:01 -04:00
|
|
|
# "ckb": "Soranî", # Kurdish (Central)
|
2022-01-17 13:33:13 -05:00
|
|
|
# "lt": "Lietuvių Kalba", # Lithuanian
|
|
|
|
# "nb_NO": "Norsk Bokmål", # Norwegian Bokmål
|
2021-02-15 18:49:54 -05:00
|
|
|
# "fa": "فارسی", # Persian
|
2022-01-17 13:33:13 -05:00
|
|
|
# "pl": "Polski", # Polish
|
2022-10-09 18:01:55 -04:00
|
|
|
# "pt_BR": "Português (Brasil)", # Portuguese Brazil
|
|
|
|
# "pt_PT": "Português (Portugal)", # Portuguese Portugal
|
2021-02-15 18:49:54 -05:00
|
|
|
# "ro": "Română", # Romanian
|
2022-10-09 18:01:55 -04:00
|
|
|
# "ru": "Русский", # Russian
|
2021-09-26 14:41:01 -04:00
|
|
|
# "sr_Latn": "Srpska (latinica)", # Serbian (latin)
|
|
|
|
# "sk": "Slovenčina", # Slovak
|
2022-10-09 18:01:55 -04:00
|
|
|
"sv": "Svenska", # Swedish
|
2021-09-26 14:41:01 -04:00
|
|
|
"es": "Español", # Spanish
|
2021-02-15 18:49:54 -05:00
|
|
|
# "te": "తెలుగు", # Telugu
|
2019-10-13 00:01:25 -04:00
|
|
|
"tr": "Türkçe", # Turkish
|
|
|
|
"uk": "Українська", # Ukrainian
|
2018-09-30 18:01:02 -04:00
|
|
|
}
|
2018-09-30 17:45:21 -04:00
|
|
|
|
2016-12-29 11:02:32 -05:00
|
|
|
# These are the default settings. They will get overwritten when loading from disk
|
2017-04-08 16:42:07 -04:00
|
|
|
self.default_settings = {
|
2019-10-13 00:01:25 -04:00
|
|
|
"version": self.common.version,
|
|
|
|
"connection_type": "bundled",
|
|
|
|
"control_port_address": "127.0.0.1",
|
|
|
|
"control_port_port": 9051,
|
|
|
|
"socks_address": "127.0.0.1",
|
|
|
|
"socks_port": 9050,
|
|
|
|
"socket_file_path": "/var/run/tor/control",
|
|
|
|
"auth_type": "no_auth",
|
|
|
|
"auth_password": "",
|
2021-10-01 13:38:49 -04:00
|
|
|
"auto_connect": False,
|
2019-10-13 00:01:25 -04:00
|
|
|
"use_autoupdate": True,
|
|
|
|
"autoupdate_timestamp": None,
|
2021-10-27 00:06:05 -04:00
|
|
|
"bridges_enabled": False,
|
|
|
|
"bridges_type": "built-in", # "built-in", "moat", or "custom"
|
|
|
|
"bridges_builtin_pt": "obfs4", # "obfs4", "meek-azure", or "snowflake"
|
|
|
|
"bridges_moat": "",
|
|
|
|
"bridges_custom": "",
|
2021-11-24 01:55:47 -05:00
|
|
|
"bridges_builtin": {},
|
2019-11-03 00:45:55 -04:00
|
|
|
"persistent_tabs": [],
|
2019-10-13 00:01:25 -04:00
|
|
|
"locale": None, # this gets defined in fill_in_defaults()
|
2021-08-20 16:24:15 -04:00
|
|
|
"theme": 0,
|
2016-12-29 11:02:32 -05:00
|
|
|
}
|
2017-04-08 16:42:07 -04:00
|
|
|
self._settings = {}
|
|
|
|
self.fill_in_defaults()
|
|
|
|
|
|
|
|
def fill_in_defaults(self):
|
|
|
|
"""
|
|
|
|
If there are any missing settings from self._settings, replace them with
|
|
|
|
their default values.
|
|
|
|
"""
|
|
|
|
for key in self.default_settings:
|
|
|
|
if key not in self._settings:
|
|
|
|
self._settings[key] = self.default_settings[key]
|
2016-12-28 22:52:21 -05:00
|
|
|
|
2018-09-30 17:45:21 -04:00
|
|
|
# Choose the default locale based on the OS preference, and fall-back to English
|
2019-10-13 00:01:25 -04:00
|
|
|
if self._settings["locale"] is None:
|
2018-12-18 21:53:40 -05:00
|
|
|
language_code, encoding = locale.getdefaultlocale()
|
|
|
|
|
|
|
|
# Default to English
|
|
|
|
if not language_code:
|
2019-10-13 00:01:25 -04:00
|
|
|
language_code = "en_US"
|
2018-12-18 21:53:40 -05:00
|
|
|
|
2019-10-13 00:01:25 -04:00
|
|
|
if language_code == "pt_PT" and language_code == "pt_BR":
|
2018-12-18 21:53:40 -05:00
|
|
|
# Portuguese locales include country code
|
|
|
|
default_locale = language_code
|
|
|
|
else:
|
|
|
|
# All other locales cut off the country code
|
|
|
|
default_locale = language_code[:2]
|
|
|
|
|
2018-09-30 17:45:21 -04:00
|
|
|
if default_locale not in self.available_locales:
|
2019-10-13 00:01:25 -04:00
|
|
|
default_locale = "en"
|
|
|
|
self._settings["locale"] = default_locale
|
2018-09-30 17:45:21 -04:00
|
|
|
|
2016-12-28 22:52:21 -05:00
|
|
|
def build_filename(self):
|
|
|
|
"""
|
|
|
|
Returns the path of the settings file.
|
|
|
|
"""
|
2019-10-13 00:01:25 -04:00
|
|
|
return os.path.join(self.common.build_data_dir(), "onionshare.json")
|
2016-12-28 22:52:21 -05:00
|
|
|
|
|
|
|
def load(self):
|
|
|
|
"""
|
|
|
|
Load the settings from file.
|
|
|
|
"""
|
2019-10-13 00:01:25 -04:00
|
|
|
self.common.log("Settings", "load")
|
2017-05-16 14:23:18 -04:00
|
|
|
|
2016-12-29 11:02:32 -05:00
|
|
|
# If the settings file exists, load it
|
2016-12-28 22:52:21 -05:00
|
|
|
if os.path.exists(self.filename):
|
|
|
|
try:
|
2019-10-20 13:15:16 -04:00
|
|
|
self.common.log("Settings", "load", f"Trying to load {self.filename}")
|
2019-10-13 00:01:25 -04:00
|
|
|
with open(self.filename, "r") as f:
|
2017-07-10 22:13:30 -04:00
|
|
|
self._settings = json.load(f)
|
2017-05-23 18:16:27 -04:00
|
|
|
self.fill_in_defaults()
|
2021-04-29 20:13:05 -04:00
|
|
|
except Exception:
|
2016-12-29 11:02:32 -05:00
|
|
|
pass
|
2016-12-28 22:52:21 -05:00
|
|
|
|
2019-01-20 14:46:20 -05:00
|
|
|
# Make sure data_dir exists
|
2018-11-25 20:34:06 -05:00
|
|
|
try:
|
2019-10-13 00:01:25 -04:00
|
|
|
os.makedirs(self.get("data_dir"), exist_ok=True)
|
2021-04-29 20:13:05 -04:00
|
|
|
except Exception:
|
2018-11-25 20:34:06 -05:00
|
|
|
pass
|
|
|
|
|
2016-12-28 22:52:21 -05:00
|
|
|
def save(self):
|
|
|
|
"""
|
|
|
|
Save settings to file.
|
|
|
|
"""
|
2019-10-13 00:01:25 -04:00
|
|
|
self.common.log("Settings", "save")
|
|
|
|
open(self.filename, "w").write(json.dumps(self._settings, indent=2))
|
2019-10-20 13:15:16 -04:00
|
|
|
self.common.log("Settings", "save", f"Settings saved in {self.filename}")
|
2016-12-28 22:52:21 -05:00
|
|
|
|
|
|
|
def get(self, key):
|
|
|
|
return self._settings[key]
|
|
|
|
|
|
|
|
def set(self, key, val):
|
2017-04-15 19:33:41 -04:00
|
|
|
# If typecasting int values fails, fallback to default values
|
2019-10-13 00:01:25 -04:00
|
|
|
if key == "control_port_port" or key == "socks_port":
|
2017-04-15 19:33:41 -04:00
|
|
|
try:
|
|
|
|
val = int(val)
|
2021-04-29 20:13:05 -04:00
|
|
|
except Exception:
|
2019-10-13 00:01:25 -04:00
|
|
|
if key == "control_port_port":
|
|
|
|
val = self.default_settings["control_port_port"]
|
|
|
|
elif key == "socks_port":
|
|
|
|
val = self.default_settings["socks_port"]
|
2017-04-15 19:33:41 -04:00
|
|
|
|
2016-12-28 22:52:21 -05:00
|
|
|
self._settings[key] = val
|