diff --git a/onionshare/__init__.py b/onionshare/__init__.py index e7c7158c..7bc18bff 100644 --- a/onionshare/__init__.py +++ b/onionshare/__init__.py @@ -282,7 +282,7 @@ def main(cwd=None): ) sys.exit() - app.start_onion_service(False, True) + app.start_onion_service(mode_settings, False, True) url = build_url(mode_settings, app, web) schedule = datetime.now() + timedelta(seconds=autostart_timer) if mode == "receive": @@ -318,9 +318,9 @@ def main(cwd=None): print("Waiting for the scheduled time before starting...") app.onion.cleanup(False) time.sleep(autostart_timer) - app.start_onion_service() + app.start_onion_service(mode_settings) else: - app.start_onion_service() + app.start_onion_service(mode_settings) except KeyboardInterrupt: print("") sys.exit() diff --git a/onionshare/mode_settings.py b/onionshare/mode_settings.py index 9557abcd..dfc0b939 100644 --- a/onionshare/mode_settings.py +++ b/onionshare/mode_settings.py @@ -17,6 +17,8 @@ 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 . """ +import os +import pwd class ModeSettings: @@ -43,7 +45,7 @@ class ModeSettings: "client_auth": False, }, "share": {"autostop_sharing": True}, - "receive": {"data_dir": self.common.settings.build_default_data_dir()}, + "receive": {"data_dir": self.build_default_data_dir()}, "website": {"disable_csp": False}, } @@ -52,3 +54,21 @@ class ModeSettings: def set(self, group, key, val): self.settings[group][key] = val + + def build_default_data_dir(self): + """ + Returns the path of the default Downloads directory for receive mode. + """ + + if self.common.platform == "Darwin": + # We can't use os.path.expanduser() in macOS because in the sandbox it + # returns the path to the sandboxed homedir + real_homedir = pwd.getpwuid(os.getuid()).pw_dir + return os.path.join(real_homedir, "OnionShare") + elif self.common.platform == "Windows": + # On Windows, os.path.expanduser() needs to use backslash, or else it + # retains the forward slash, which breaks opening the folder in explorer. + return os.path.expanduser("~\OnionShare") + else: + # All other OSes + return os.path.expanduser("~/OnionShare") diff --git a/onionshare/onionshare.py b/onionshare/onionshare.py index a5c03ea3..f4828140 100644 --- a/onionshare/onionshare.py +++ b/onionshare/onionshare.py @@ -63,7 +63,9 @@ class OnionShare(object): except: raise OSError(strings._("no_available_port")) - def start_onion_service(self, await_publication=True, save_scheduled_key=False): + def start_onion_service( + self, mode_settings, await_publication=True, save_scheduled_key=False + ): """ Start the onionshare onion service. """ @@ -83,7 +85,7 @@ class OnionShare(object): self.port, await_publication, save_scheduled_key ) - if self.stealth: + if mode_settings.get("general", "client_auth"): self.auth_string = self.onion.auth_string def cleanup(self): diff --git a/onionshare/settings.py b/onionshare/settings.py index 00854204..6d6528a4 100644 --- a/onionshare/settings.py +++ b/onionshare/settings.py @@ -122,7 +122,7 @@ class Settings(object): "public_mode": False, "password": "", "hidservauth_string": "", - "data_dir": self.build_default_data_dir(), + "data_dir": "", "csp_header_disabled": False, "locale": None, # this gets defined in fill_in_defaults() } @@ -163,24 +163,6 @@ class Settings(object): """ return os.path.join(self.common.build_data_dir(), "onionshare.json") - def build_default_data_dir(self): - """ - Returns the path of the default Downloads directory for receive mode. - """ - - if self.common.platform == "Darwin": - # We can't use os.path.expanduser() in macOS because in the sandbox it - # returns the path to the sandboxed homedir - real_homedir = pwd.getpwuid(os.getuid()).pw_dir - return os.path.join(real_homedir, "OnionShare") - elif self.common.platform == "Windows": - # On Windows, os.path.expanduser() needs to use backslash, or else it - # retains the forward slash, which breaks opening the folder in explorer. - return os.path.expanduser("~\OnionShare") - else: - # All other OSes - return os.path.expanduser("~/OnionShare") - def load(self): """ Load the settings from file. diff --git a/onionshare/web/share_mode.py b/onionshare/web/share_mode.py index 60c8eca0..16a16a0b 100644 --- a/onionshare/web/share_mode.py +++ b/onionshare/web/share_mode.py @@ -38,7 +38,7 @@ class ShareModeWeb(SendBaseModeWeb): # Deny new downloads if "Stop sharing after files have been sent" is checked and there is # currently a download deny_download = ( - not self.web.settings.get("share", "autostop_sharing") + self.web.settings.get("share", "autostop_sharing") and self.download_in_progress ) if deny_download: @@ -64,7 +64,7 @@ class ShareModeWeb(SendBaseModeWeb): # Deny new downloads if "Stop After First Download" is checked and there is # currently a download deny_download = ( - not self.web.settings.get("share", "autostop_sharing") + self.web.settings.get("share", "autostop_sharing") and self.download_in_progress ) if deny_download: @@ -102,7 +102,7 @@ class ShareModeWeb(SendBaseModeWeb): def generate(): # Starting a new download - if not self.web.settings.get("share", "autostop_sharing"): + if self.web.settings.get("share", "autostop_sharing"): self.download_in_progress = True chunk_size = 102400 # 100kb @@ -167,14 +167,11 @@ class ShareModeWeb(SendBaseModeWeb): sys.stdout.write("\n") # Download is finished - if not self.web.settings.get("share", "autostop_sharing"): + if self.web.settings.get("share", "autostop_sharing"): self.download_in_progress = False # Close the server, if necessary - if ( - not self.web.settings.get("share", "autostop_sharing") - and not canceled - ): + if self.web.settings.get("share", "autostop_sharing") and not canceled: print("Stopped because transfer is complete") self.web.running = False try: diff --git a/onionshare_gui/threads.py b/onionshare_gui/threads.py index 090574c1..a507b70f 100644 --- a/onionshare_gui/threads.py +++ b/onionshare_gui/threads.py @@ -61,7 +61,7 @@ class OnionThread(QtCore.QThread): try: if self.mode.obtain_onion_early: self.mode.app.start_onion_service( - await_publication=False, save_scheduled_key=True + self.mode.settings, await_publication=False, save_scheduled_key=True ) # wait for modules in thread to load, preventing a thread-related cx_Freeze crash time.sleep(0.2) @@ -69,7 +69,9 @@ class OnionThread(QtCore.QThread): # Unregister the onion so we can use it in the next OnionThread self.mode.app.onion.cleanup(False) else: - self.mode.app.start_onion_service(await_publication=True) + self.mode.app.start_onion_service( + self.mode.settings, await_publication=True + ) # wait for modules in thread to load, preventing a thread-related cx_Freeze crash time.sleep(0.2) # start onionshare http service in new thread diff --git a/tests/test_onionshare.py b/tests/test_onionshare.py index 64b16b1f..0addf6d5 100644 --- a/tests/test_onionshare.py +++ b/tests/test_onionshare.py @@ -23,13 +23,13 @@ import pytest from onionshare import OnionShare from onionshare.common import Common +from onionshare.mode_settings import ModeSettings class MyOnion: - def __init__(self, stealth=False): + def __init__(self): self.auth_string = "TestHidServAuth" self.private_key = "" - self.stealth = stealth self.scheduled_key = None @staticmethod @@ -43,38 +43,27 @@ def onionshare_obj(): return OnionShare(common, MyOnion()) +@pytest.fixture +def mode_settings_obj(): + common = Common() + return ModeSettings(common) + + class TestOnionShare: def test_init(self, onionshare_obj): assert onionshare_obj.hidserv_dir is None assert onionshare_obj.onion_host is None - assert onionshare_obj.stealth is None assert onionshare_obj.cleanup_filenames == [] assert onionshare_obj.local_only is False - def test_set_stealth_true(self, onionshare_obj): - onionshare_obj.set_stealth(True) - assert onionshare_obj.stealth is True - assert onionshare_obj.onion.stealth is True - - def test_set_stealth_false(self, onionshare_obj): - onionshare_obj.set_stealth(False) - assert onionshare_obj.stealth is False - assert onionshare_obj.onion.stealth is False - - def test_start_onion_service(self, onionshare_obj): - onionshare_obj.set_stealth(False) - onionshare_obj.start_onion_service() + def test_start_onion_service(self, onionshare_obj, mode_settings_obj): + onionshare_obj.start_onion_service(mode_settings_obj) assert 17600 <= onionshare_obj.port <= 17650 assert onionshare_obj.onion_host == "test_service_id.onion" - def test_start_onion_service_stealth(self, onionshare_obj): - onionshare_obj.set_stealth(True) - onionshare_obj.start_onion_service() - assert onionshare_obj.auth_string == "TestHidServAuth" - - def test_start_onion_service_local_only(self, onionshare_obj): + def test_start_onion_service_local_only(self, onionshare_obj, mode_settings_obj): onionshare_obj.local_only = True - onionshare_obj.start_onion_service() + onionshare_obj.start_onion_service(mode_settings_obj) assert onionshare_obj.onion_host == "127.0.0.1:{}".format(onionshare_obj.port) def test_cleanup(self, onionshare_obj, temp_dir_1024, temp_file_1024): diff --git a/tests/test_onionshare_web.py b/tests/test_onionshare_web.py index c3a0807c..2ce2f758 100644 --- a/tests/test_onionshare_web.py +++ b/tests/test_onionshare_web.py @@ -36,6 +36,7 @@ from onionshare.common import Common from onionshare import strings from onionshare.web import Web from onionshare.settings import Settings +from onionshare.mode_settings import ModeSettings DEFAULT_ZW_FILENAME_REGEX = re.compile(r"^onionshare_[a-z2-7]{6}.zip$") RANDOM_STR_REGEX = re.compile(r"^[a-z2-7]+$") @@ -45,9 +46,9 @@ def web_obj(common_obj, mode, num_files=0): """ Creates a Web object, in either share mode or receive mode, ready for testing """ common_obj.settings = Settings(common_obj) strings.load_strings(common_obj) - web = Web(common_obj, False, mode) + mode_settings = ModeSettings(common_obj) + web = Web(common_obj, False, mode_settings, mode) web.generate_password() - web.stay_open = True web.running = True web.app.testing = True @@ -56,7 +57,7 @@ def web_obj(common_obj, mode, num_files=0): if mode == "share": # Add files files = [] - for i in range(num_files): + for _ in range(num_files): with tempfile.NamedTemporaryFile(delete=False) as tmp_file: tmp_file.write(b"*" * 1024) files.append(tmp_file.name) @@ -94,9 +95,9 @@ class TestWeb: assert res.status_code == 200 assert res.mimetype == "application/zip" - def test_share_mode_close_after_first_download_on(self, common_obj, temp_file_1024): + def test_share_mode_autostop_sharing_on(self, common_obj, temp_file_1024): web = web_obj(common_obj, "share", 3) - web.stay_open = False + web.settings.set("share", "autostop_sharing", True) assert web.running == True @@ -109,11 +110,9 @@ class TestWeb: assert web.running == False - def test_share_mode_close_after_first_download_off( - self, common_obj, temp_file_1024 - ): + def test_share_mode_autostop_sharing_off(self, common_obj, temp_file_1024): web = web_obj(common_obj, "share", 3) - web.stay_open = True + web.settings.set("share", "autostop_sharing", False) assert web.running == True @@ -147,7 +146,7 @@ class TestWeb: def test_public_mode_on(self, common_obj): web = web_obj(common_obj, "receive") - common_obj.settings.set("public_mode", True) + web.settings.set("general", "public", True) with web.app.test_client() as c: # Loading / should work without auth @@ -157,7 +156,7 @@ class TestWeb: def test_public_mode_off(self, common_obj): web = web_obj(common_obj, "receive") - common_obj.settings.set("public_mode", False) + web.settings.set("general", "public", False) with web.app.test_client() as c: # Load / without auth