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

View File

@ -177,15 +177,24 @@ class Common:
os.makedirs(onionshare_data_dir, 0o700, True)
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:
wordlist = f.read().split()
r = random.SystemRandom()
return "-".join(r.choice(wordlist) for _ in range(2))
return "-".join(r.choice(wordlist) for _ in range(word_count))
@staticmethod
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 pwd
import json
class ModeSettings:
@ -27,10 +28,10 @@ class ModeSettings:
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.settings = {
self.default_settings = {
"persistent": {
"enabled": False,
"private_key": None,
@ -44,16 +45,41 @@ class ModeSettings:
"legacy": False,
"client_auth": False,
},
"share": {"autostop_sharing": True},
"share": {"autostop_sharing": True, "filenames": []},
"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):
return self.settings[group][key]
return self._settings[group][key]
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):
"""
@ -73,6 +99,39 @@ class ModeSettings:
# All other OSes
return os.path.expanduser("~/OnionShare")
def load(self, filename=None):
# 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
# 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):
# TODO: save settings, if persistent
pass
# 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))