diff options
Diffstat (limited to 'cli/onionshare_cli/settings.py')
-rw-r--r-- | cli/onionshare_cli/settings.py | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/cli/onionshare_cli/settings.py b/cli/onionshare_cli/settings.py new file mode 100644 index 00000000..82fcd6b9 --- /dev/null +++ b/cli/onionshare_cli/settings.py @@ -0,0 +1,197 @@ +# -*- coding: utf-8 -*- +""" +OnionShare | https://onionshare.org/ + +Copyright (C) 2014-2020 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 json +import os +import platform +import locale + +try: + # We only need pwd module in macOS, and it's not available in Windows + import pwd +except: + pass + + +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. + """ + + def __init__(self, common, config=False): + self.common = common + + self.common.log("Settings", "__init__") + + # If a readable config file was provided, use that instead + if config: + if os.path.isfile(config): + self.filename = config + else: + self.common.log( + "Settings", + "__init__", + "Supplied config does not exist or is unreadable. Falling back to default location", + ) + self.filename = self.build_filename() + + else: + # Default config + self.filename = self.build_filename() + + # Dictionary of available languages in this version of OnionShare, + # mapped to the language name, in that language + self.available_locales = { + "ar": "العربية", # Arabic + #'bn': 'বাংলা', # Bengali (commented out because not at 90% translation) + "ca": "Català", # Catalan + "zh_Hant": "正體中文 (繁體)", # Traditional Chinese + "zh_Hans": "中文 (简体)", # Simplified Chinese + "da": "Dansk", # Danish + "nl": "Nederlands", # Dutch + "en": "English", # English + # "fi": "Suomi", # Finnish (commented out because not at 90% translation) + "fr": "Français", # French + "de": "Deutsch", # German + "el": "Ελληνικά", # Greek + "is": "Íslenska", # Icelandic + "ga": "Gaeilge", # Irish + "it": "Italiano", # Italian + "ja": "日本語", # Japanese + "nb_NO": "Norsk Bokmål", # Norwegian Bokmål + "fa": "فارسی", # Persian + "pl": "Polski", # Polish + "pt_BR": "Português (Brasil)", # Portuguese Brazil + "pt_PT": "Português (Portugal)", # Portuguese Portugal + "ro": "Română", # Romanian + "ru": "Русский", # Russian + "sr_Latn": "Srpska (latinica)", # Serbian (latin) + "es": "Español", # Spanish + "sv": "Svenska", # Swedish + "te": "తెలుగు", # Telugu + "tr": "Türkçe", # Turkish + "uk": "Українська", # Ukrainian + } + + # These are the default settings. They will get overwritten when loading from disk + self.default_settings = { + "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": "", + "use_autoupdate": True, + "autoupdate_timestamp": None, + "no_bridges": True, + "tor_bridges_use_obfs4": False, + "tor_bridges_use_meek_lite_azure": False, + "tor_bridges_use_custom_bridges": "", + "persistent_tabs": [], + "locale": None, # this gets defined in fill_in_defaults() + } + 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] + + # Choose the default locale based on the OS preference, and fall-back to English + if self._settings["locale"] is None: + language_code, encoding = locale.getdefaultlocale() + + # Default to English + if not language_code: + language_code = "en_US" + + if language_code == "pt_PT" and language_code == "pt_BR": + # Portuguese locales include country code + default_locale = language_code + else: + # All other locales cut off the country code + default_locale = language_code[:2] + + if default_locale not in self.available_locales: + default_locale = "en" + self._settings["locale"] = default_locale + + def build_filename(self): + """ + Returns the path of the settings file. + """ + return os.path.join(self.common.build_data_dir(), "onionshare.json") + + def load(self): + """ + Load the settings from file. + """ + self.common.log("Settings", "load") + + # If the settings file exists, load it + if os.path.exists(self.filename): + try: + self.common.log("Settings", "load", f"Trying to load {self.filename}") + with open(self.filename, "r") as f: + self._settings = json.load(f) + self.fill_in_defaults() + except: + pass + + # Make sure data_dir exists + try: + os.makedirs(self.get("data_dir"), exist_ok=True) + except: + pass + + def save(self): + """ + Save settings to file. + """ + self.common.log("Settings", "save") + open(self.filename, "w").write(json.dumps(self._settings, indent=2)) + self.common.log("Settings", "save", f"Settings saved in {self.filename}") + + def get(self, key): + return self._settings[key] + + def set(self, key, val): + # If typecasting int values fails, fallback to default values + if key == "control_port_port" or key == "socks_port": + try: + val = int(val) + except: + if key == "control_port_port": + val = self.default_settings["control_port_port"] + elif key == "socks_port": + val = self.default_settings["socks_port"] + + self._settings[key] = val |