aboutsummaryrefslogtreecommitdiff
path: root/onionshare
diff options
context:
space:
mode:
authorMicah Lee <micah@micahflee.com>2019-11-02 21:00:23 -0700
committerMicah Lee <micah@micahflee.com>2019-11-02 21:00:23 -0700
commit1b36fe4036e5963ef702273b8d2218f5c043c4ed (patch)
tree96c0ee3c814b33dd0699b796f0483e8e0cf03ae8 /onionshare
parent69bd16527890c06b573b9f6b939bf72895daae95 (diff)
downloadonionshare-1b36fe4036e5963ef702273b8d2218f5c043c4ed.tar.gz
onionshare-1b36fe4036e5963ef702273b8d2218f5c043c4ed.zip
Make ModeSettings be able to save and load
Diffstat (limited to 'onionshare')
-rw-r--r--onionshare/__init__.py53
-rw-r--r--onionshare/common.py15
-rw-r--r--onionshare/mode_settings.py75
3 files changed, 107 insertions, 36 deletions
diff --git a/onionshare/__init__.py b/onionshare/__init__.py
index 7bc18bff..f532ec0e 100644
--- a/onionshare/__init__.py
+++ b/onionshare/__init__.py
@@ -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,
)
diff --git a/onionshare/common.py b/onionshare/common.py
index ac79f43b..5245ddf9 100644
--- a/onionshare/common.py
+++ b/onionshare/common.py
@@ -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):
diff --git a/onionshare/mode_settings.py b/onionshare/mode_settings.py
index 2eab8f6e..ffc32d06 100644
--- a/onionshare/mode_settings.py
+++ b/onionshare/mode_settings.py
@@ -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))