mirror of
https://github.com/onionshare/onionshare.git
synced 2025-06-06 13:59:15 -04:00
Fix CLI tests, and also fix bug related to autostop_sharing that the tests found
This commit is contained in:
parent
598db21dcd
commit
87918c5d89
8 changed files with 60 additions and 69 deletions
|
@ -282,7 +282,7 @@ def main(cwd=None):
|
||||||
)
|
)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
app.start_onion_service(False, True)
|
app.start_onion_service(mode_settings, False, True)
|
||||||
url = build_url(mode_settings, app, web)
|
url = build_url(mode_settings, app, web)
|
||||||
schedule = datetime.now() + timedelta(seconds=autostart_timer)
|
schedule = datetime.now() + timedelta(seconds=autostart_timer)
|
||||||
if mode == "receive":
|
if mode == "receive":
|
||||||
|
@ -318,9 +318,9 @@ def main(cwd=None):
|
||||||
print("Waiting for the scheduled time before starting...")
|
print("Waiting for the scheduled time before starting...")
|
||||||
app.onion.cleanup(False)
|
app.onion.cleanup(False)
|
||||||
time.sleep(autostart_timer)
|
time.sleep(autostart_timer)
|
||||||
app.start_onion_service()
|
app.start_onion_service(mode_settings)
|
||||||
else:
|
else:
|
||||||
app.start_onion_service()
|
app.start_onion_service(mode_settings)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("")
|
print("")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
|
@ -17,6 +17,8 @@ GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
|
import pwd
|
||||||
|
|
||||||
|
|
||||||
class ModeSettings:
|
class ModeSettings:
|
||||||
|
@ -43,7 +45,7 @@ class ModeSettings:
|
||||||
"client_auth": False,
|
"client_auth": False,
|
||||||
},
|
},
|
||||||
"share": {"autostop_sharing": True},
|
"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},
|
"website": {"disable_csp": False},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,3 +54,21 @@ class ModeSettings:
|
||||||
|
|
||||||
def set(self, group, key, val):
|
def set(self, group, key, val):
|
||||||
self.settings[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")
|
||||||
|
|
|
@ -63,7 +63,9 @@ class OnionShare(object):
|
||||||
except:
|
except:
|
||||||
raise OSError(strings._("no_available_port"))
|
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.
|
Start the onionshare onion service.
|
||||||
"""
|
"""
|
||||||
|
@ -83,7 +85,7 @@ class OnionShare(object):
|
||||||
self.port, await_publication, save_scheduled_key
|
self.port, await_publication, save_scheduled_key
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.stealth:
|
if mode_settings.get("general", "client_auth"):
|
||||||
self.auth_string = self.onion.auth_string
|
self.auth_string = self.onion.auth_string
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
|
|
|
@ -122,7 +122,7 @@ class Settings(object):
|
||||||
"public_mode": False,
|
"public_mode": False,
|
||||||
"password": "",
|
"password": "",
|
||||||
"hidservauth_string": "",
|
"hidservauth_string": "",
|
||||||
"data_dir": self.build_default_data_dir(),
|
"data_dir": "",
|
||||||
"csp_header_disabled": False,
|
"csp_header_disabled": False,
|
||||||
"locale": None, # this gets defined in fill_in_defaults()
|
"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")
|
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):
|
def load(self):
|
||||||
"""
|
"""
|
||||||
Load the settings from file.
|
Load the settings from file.
|
||||||
|
|
|
@ -38,7 +38,7 @@ class ShareModeWeb(SendBaseModeWeb):
|
||||||
# Deny new downloads if "Stop sharing after files have been sent" is checked and there is
|
# Deny new downloads if "Stop sharing after files have been sent" is checked and there is
|
||||||
# currently a download
|
# currently a download
|
||||||
deny_download = (
|
deny_download = (
|
||||||
not self.web.settings.get("share", "autostop_sharing")
|
self.web.settings.get("share", "autostop_sharing")
|
||||||
and self.download_in_progress
|
and self.download_in_progress
|
||||||
)
|
)
|
||||||
if deny_download:
|
if deny_download:
|
||||||
|
@ -64,7 +64,7 @@ class ShareModeWeb(SendBaseModeWeb):
|
||||||
# Deny new downloads if "Stop After First Download" is checked and there is
|
# Deny new downloads if "Stop After First Download" is checked and there is
|
||||||
# currently a download
|
# currently a download
|
||||||
deny_download = (
|
deny_download = (
|
||||||
not self.web.settings.get("share", "autostop_sharing")
|
self.web.settings.get("share", "autostop_sharing")
|
||||||
and self.download_in_progress
|
and self.download_in_progress
|
||||||
)
|
)
|
||||||
if deny_download:
|
if deny_download:
|
||||||
|
@ -102,7 +102,7 @@ class ShareModeWeb(SendBaseModeWeb):
|
||||||
|
|
||||||
def generate():
|
def generate():
|
||||||
# Starting a new download
|
# 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
|
self.download_in_progress = True
|
||||||
|
|
||||||
chunk_size = 102400 # 100kb
|
chunk_size = 102400 # 100kb
|
||||||
|
@ -167,14 +167,11 @@ class ShareModeWeb(SendBaseModeWeb):
|
||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
|
|
||||||
# Download is finished
|
# 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
|
self.download_in_progress = False
|
||||||
|
|
||||||
# Close the server, if necessary
|
# Close the server, if necessary
|
||||||
if (
|
if self.web.settings.get("share", "autostop_sharing") and not canceled:
|
||||||
not self.web.settings.get("share", "autostop_sharing")
|
|
||||||
and not canceled
|
|
||||||
):
|
|
||||||
print("Stopped because transfer is complete")
|
print("Stopped because transfer is complete")
|
||||||
self.web.running = False
|
self.web.running = False
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -61,7 +61,7 @@ class OnionThread(QtCore.QThread):
|
||||||
try:
|
try:
|
||||||
if self.mode.obtain_onion_early:
|
if self.mode.obtain_onion_early:
|
||||||
self.mode.app.start_onion_service(
|
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
|
# wait for modules in thread to load, preventing a thread-related cx_Freeze crash
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
@ -69,7 +69,9 @@ class OnionThread(QtCore.QThread):
|
||||||
# Unregister the onion so we can use it in the next OnionThread
|
# Unregister the onion so we can use it in the next OnionThread
|
||||||
self.mode.app.onion.cleanup(False)
|
self.mode.app.onion.cleanup(False)
|
||||||
else:
|
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
|
# wait for modules in thread to load, preventing a thread-related cx_Freeze crash
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
# start onionshare http service in new thread
|
# start onionshare http service in new thread
|
||||||
|
|
|
@ -23,13 +23,13 @@ import pytest
|
||||||
|
|
||||||
from onionshare import OnionShare
|
from onionshare import OnionShare
|
||||||
from onionshare.common import Common
|
from onionshare.common import Common
|
||||||
|
from onionshare.mode_settings import ModeSettings
|
||||||
|
|
||||||
|
|
||||||
class MyOnion:
|
class MyOnion:
|
||||||
def __init__(self, stealth=False):
|
def __init__(self):
|
||||||
self.auth_string = "TestHidServAuth"
|
self.auth_string = "TestHidServAuth"
|
||||||
self.private_key = ""
|
self.private_key = ""
|
||||||
self.stealth = stealth
|
|
||||||
self.scheduled_key = None
|
self.scheduled_key = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -43,38 +43,27 @@ def onionshare_obj():
|
||||||
return OnionShare(common, MyOnion())
|
return OnionShare(common, MyOnion())
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mode_settings_obj():
|
||||||
|
common = Common()
|
||||||
|
return ModeSettings(common)
|
||||||
|
|
||||||
|
|
||||||
class TestOnionShare:
|
class TestOnionShare:
|
||||||
def test_init(self, onionshare_obj):
|
def test_init(self, onionshare_obj):
|
||||||
assert onionshare_obj.hidserv_dir is None
|
assert onionshare_obj.hidserv_dir is None
|
||||||
assert onionshare_obj.onion_host is None
|
assert onionshare_obj.onion_host is None
|
||||||
assert onionshare_obj.stealth is None
|
|
||||||
assert onionshare_obj.cleanup_filenames == []
|
assert onionshare_obj.cleanup_filenames == []
|
||||||
assert onionshare_obj.local_only is False
|
assert onionshare_obj.local_only is False
|
||||||
|
|
||||||
def test_set_stealth_true(self, onionshare_obj):
|
def test_start_onion_service(self, onionshare_obj, mode_settings_obj):
|
||||||
onionshare_obj.set_stealth(True)
|
onionshare_obj.start_onion_service(mode_settings_obj)
|
||||||
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()
|
|
||||||
assert 17600 <= onionshare_obj.port <= 17650
|
assert 17600 <= onionshare_obj.port <= 17650
|
||||||
assert onionshare_obj.onion_host == "test_service_id.onion"
|
assert onionshare_obj.onion_host == "test_service_id.onion"
|
||||||
|
|
||||||
def test_start_onion_service_stealth(self, onionshare_obj):
|
def test_start_onion_service_local_only(self, onionshare_obj, mode_settings_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):
|
|
||||||
onionshare_obj.local_only = True
|
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)
|
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):
|
def test_cleanup(self, onionshare_obj, temp_dir_1024, temp_file_1024):
|
||||||
|
|
|
@ -36,6 +36,7 @@ from onionshare.common import Common
|
||||||
from onionshare import strings
|
from onionshare import strings
|
||||||
from onionshare.web import Web
|
from onionshare.web import Web
|
||||||
from onionshare.settings import Settings
|
from onionshare.settings import Settings
|
||||||
|
from onionshare.mode_settings import ModeSettings
|
||||||
|
|
||||||
DEFAULT_ZW_FILENAME_REGEX = re.compile(r"^onionshare_[a-z2-7]{6}.zip$")
|
DEFAULT_ZW_FILENAME_REGEX = re.compile(r"^onionshare_[a-z2-7]{6}.zip$")
|
||||||
RANDOM_STR_REGEX = re.compile(r"^[a-z2-7]+$")
|
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 """
|
""" Creates a Web object, in either share mode or receive mode, ready for testing """
|
||||||
common_obj.settings = Settings(common_obj)
|
common_obj.settings = Settings(common_obj)
|
||||||
strings.load_strings(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.generate_password()
|
||||||
web.stay_open = True
|
|
||||||
web.running = True
|
web.running = True
|
||||||
|
|
||||||
web.app.testing = True
|
web.app.testing = True
|
||||||
|
@ -56,7 +57,7 @@ def web_obj(common_obj, mode, num_files=0):
|
||||||
if mode == "share":
|
if mode == "share":
|
||||||
# Add files
|
# Add files
|
||||||
files = []
|
files = []
|
||||||
for i in range(num_files):
|
for _ in range(num_files):
|
||||||
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
|
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
|
||||||
tmp_file.write(b"*" * 1024)
|
tmp_file.write(b"*" * 1024)
|
||||||
files.append(tmp_file.name)
|
files.append(tmp_file.name)
|
||||||
|
@ -94,9 +95,9 @@ class TestWeb:
|
||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
assert res.mimetype == "application/zip"
|
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 = web_obj(common_obj, "share", 3)
|
||||||
web.stay_open = False
|
web.settings.set("share", "autostop_sharing", True)
|
||||||
|
|
||||||
assert web.running == True
|
assert web.running == True
|
||||||
|
|
||||||
|
@ -109,11 +110,9 @@ class TestWeb:
|
||||||
|
|
||||||
assert web.running == False
|
assert web.running == False
|
||||||
|
|
||||||
def test_share_mode_close_after_first_download_off(
|
def test_share_mode_autostop_sharing_off(self, common_obj, temp_file_1024):
|
||||||
self, common_obj, temp_file_1024
|
|
||||||
):
|
|
||||||
web = web_obj(common_obj, "share", 3)
|
web = web_obj(common_obj, "share", 3)
|
||||||
web.stay_open = True
|
web.settings.set("share", "autostop_sharing", False)
|
||||||
|
|
||||||
assert web.running == True
|
assert web.running == True
|
||||||
|
|
||||||
|
@ -147,7 +146,7 @@ class TestWeb:
|
||||||
|
|
||||||
def test_public_mode_on(self, common_obj):
|
def test_public_mode_on(self, common_obj):
|
||||||
web = web_obj(common_obj, "receive")
|
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:
|
with web.app.test_client() as c:
|
||||||
# Loading / should work without auth
|
# Loading / should work without auth
|
||||||
|
@ -157,7 +156,7 @@ class TestWeb:
|
||||||
|
|
||||||
def test_public_mode_off(self, common_obj):
|
def test_public_mode_off(self, common_obj):
|
||||||
web = web_obj(common_obj, "receive")
|
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:
|
with web.app.test_client() as c:
|
||||||
# Load / without auth
|
# Load / without auth
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue