Make ModeSettings be able to save and load

This commit is contained in:
Micah Lee 2019-11-02 21:00:23 -07:00
parent 69bd165278
commit 1b36fe4036
No known key found for this signature in database
GPG Key ID: 403C2657CD994F73
3 changed files with 107 additions and 36 deletions

View File

@ -73,21 +73,21 @@ def main(cwd=None):
) )
parser.add_argument( parser.add_argument(
"--connect-timeout", "--connect-timeout",
metavar="<int>", metavar="SECONDS",
dest="connect_timeout", dest="connect_timeout",
default=120, default=120,
help="Give up connecting to Tor after a given amount of seconds (default: 120)", help="Give up connecting to Tor after a given amount of seconds (default: 120)",
) )
parser.add_argument( parser.add_argument(
"--config", "--config",
metavar="config", metavar="FILENAME",
default=None, default=None,
help="Filename of custom global settings", help="Filename of custom global settings",
) )
# Persistent file # Persistent file
parser.add_argument( parser.add_argument(
"--persistent", "--persistent",
metavar="persistent", metavar="FILENAME",
default=None, default=None,
help="Filename of persistent session", help="Filename of persistent session",
) )
@ -101,14 +101,14 @@ def main(cwd=None):
) )
parser.add_argument( parser.add_argument(
"--auto-start-timer", "--auto-start-timer",
metavar="<int>", metavar="SECONDS",
dest="autostart_timer", dest="autostart_timer",
default=0, default=0,
help="Start onion service at scheduled time (N seconds from now)", help="Start onion service at scheduled time (N seconds from now)",
) )
parser.add_argument( parser.add_argument(
"--auto-stop-timer", "--auto-stop-timer",
metavar="<int>", metavar="SECONDS",
dest="autostop_timer", dest="autostop_timer",
default=0, default=0,
help="Stop onion service at schedule time (N seconds from now)", help="Stop onion service at schedule time (N seconds from now)",
@ -174,8 +174,8 @@ def main(cwd=None):
website = bool(args.website) website = bool(args.website)
local_only = bool(args.local_only) local_only = bool(args.local_only)
connect_timeout = int(args.connect_timeout) connect_timeout = int(args.connect_timeout)
config = args.config config_filename = args.config
persistent = args.persistent persistent_filename = args.persistent
public = bool(args.public) public = bool(args.public)
autostart_timer = int(args.autostart_timer) autostart_timer = int(args.autostart_timer)
autostop_timer = int(args.autostop_timer) autostop_timer = int(args.autostop_timer)
@ -220,8 +220,8 @@ def main(cwd=None):
sys.exit() sys.exit()
# Re-load settings, if a custom config was passed in # Re-load settings, if a custom config was passed in
if config: if config_filename:
common.load_settings(config) common.load_settings(config_filename)
else: else:
common.load_settings() common.load_settings()
@ -229,7 +229,12 @@ def main(cwd=None):
common.verbose = verbose common.verbose = verbose
# Mode settings # Mode settings
if persistent_filename:
mode_settings = ModeSettings(common, persistent_filename)
mode_settings.set("persistent", "enabled", True)
else:
mode_settings = ModeSettings(common) mode_settings = ModeSettings(common)
if mode_settings.just_created:
mode_settings.set("general", "public", public) mode_settings.set("general", "public", public)
mode_settings.set("general", "autostart_timer", autostart_timer) mode_settings.set("general", "autostart_timer", autostart_timer)
mode_settings.set("general", "autostop_timer", autostop_timer) mode_settings.set("general", "autostop_timer", autostop_timer)
@ -243,8 +248,6 @@ def main(cwd=None):
if mode == "website": if mode == "website":
mode_settings.set("website", "disable_csp", disable_csp) mode_settings.set("website", "disable_csp", disable_csp)
# TODO: handle persistent
# Create the Web object # Create the Web object
web = Web(common, False, mode_settings, mode) web = Web(common, False, mode_settings, mode)
@ -253,7 +256,7 @@ def main(cwd=None):
try: try:
onion.connect( onion.connect(
custom_settings=False, custom_settings=False,
config=config, config=config_filename,
connect_timeout=connect_timeout, connect_timeout=connect_timeout,
local_only=local_only, local_only=local_only,
) )

View File

@ -177,15 +177,24 @@ class Common:
os.makedirs(onionshare_data_dir, 0o700, True) os.makedirs(onionshare_data_dir, 0o700, True)
return onionshare_data_dir return onionshare_data_dir
def build_password(self): def build_persistent_dir(self):
""" """
Returns a random string made from two words from the wordlist, such as "deter-trig". Returns the path to the folder that holds persistent files
"""
onionshare_data_dir = self.build_data_dir()
persistent_dir = os.path.join(onionshare_data_dir, "persistent")
os.makedirs(persistent_dir, 0o700, True)
return persistent_dir
def build_password(self, word_count=2):
"""
Returns a random string made of words from the wordlist, such as "deter-trig".
""" """
with open(self.get_resource_path("wordlist.txt")) as f: with open(self.get_resource_path("wordlist.txt")) as f:
wordlist = f.read().split() wordlist = f.read().split()
r = random.SystemRandom() r = random.SystemRandom()
return "-".join(r.choice(wordlist) for _ in range(2)) return "-".join(r.choice(wordlist) for _ in range(word_count))
@staticmethod @staticmethod
def random_string(num_bytes, output_len=None): def random_string(num_bytes, output_len=None):

View File

@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import os import os
import pwd import pwd
import json
class ModeSettings: class ModeSettings:
@ -27,10 +28,10 @@ class ModeSettings:
is only one TabSettings, and in the GUI there is a separate TabSettings for each tab is only one TabSettings, and in the GUI there is a separate TabSettings for each tab
""" """
def __init__(self, common): def __init__(self, common, filename=None):
self.common = common self.common = common
self.settings = { self.default_settings = {
"persistent": { "persistent": {
"enabled": False, "enabled": False,
"private_key": None, "private_key": None,
@ -44,16 +45,41 @@ class ModeSettings:
"legacy": False, "legacy": False,
"client_auth": False, "client_auth": False,
}, },
"share": {"autostop_sharing": True}, "share": {"autostop_sharing": True, "filenames": []},
"receive": {"data_dir": self.build_default_receive_data_dir()}, "receive": {"data_dir": self.build_default_receive_data_dir()},
"website": {"disable_csp": False}, "website": {"disable_csp": False, "filenames": []},
} }
self._settings = {}
self.just_created = False
self.id = self.common.build_password(3)
self.load(filename)
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 in self._settings:
for inner_key in self.default_settings[key]:
if inner_key not in self._settings[key]:
self._settings[key][inner_key] = self.default_settings[key][
inner_key
]
else:
self._settings[key] = self.default_settings[key]
def get(self, group, key): def get(self, group, key):
return self.settings[group][key] return self._settings[group][key]
def set(self, group, key, val): def set(self, group, key, val):
self.settings[group][key] = val self._settings[group][key] = val
self.common.log(
"ModeSettings", "set", f"updating {self.id}: {group}.{key} = {val}"
)
self.save()
def build_default_receive_data_dir(self): def build_default_receive_data_dir(self):
""" """
@ -73,6 +99,39 @@ class ModeSettings:
# All other OSes # All other OSes
return os.path.expanduser("~/OnionShare") return os.path.expanduser("~/OnionShare")
def save(self): def load(self, filename=None):
# TODO: save settings, if persistent # Load persistent settings from disk. If the file doesn't exist, create it
if filename:
self.filename = filename
else:
# Give it a persistent filename
self.filename = os.path.join(
self.common.build_persistent_dir(), f"{self.id}.json"
)
if os.path.exists(self.filename):
try:
with open(self.filename, "r") as f:
self._settings = json.load(f)
self.fill_in_defaults()
self.common.log("ModeSettings", "load", f"loaded {self.filename}")
return
except:
pass pass
# If loading settings didn't work, create the settings file
self.common.log("ModeSettings", "load", f"creating {self.filename}")
self.fill_in_defaults()
self.just_created = True
def save(self):
# Save persistent setting to disk
if not self.get("persistent", "enabled"):
self.common.log(
"ModeSettings", "save", f"{self.id}: not persistent, so not saving"
)
return
if self.filename:
with open(self.filename, "w") as file:
file.write(json.dumps(self._settings, indent=2))