mirror of
https://github.com/onionshare/onionshare.git
synced 2025-02-05 09:25:37 -05:00
Refactor onionshare CLI to accept and use all mode settings
This commit is contained in:
parent
b8f1299496
commit
9f0e031c8b
@ -29,9 +29,9 @@ from .onionshare import OnionShare
|
|||||||
from .mode_settings import ModeSettings
|
from .mode_settings import ModeSettings
|
||||||
|
|
||||||
|
|
||||||
def build_url(common, app, web):
|
def build_url(mode_settings, app, web):
|
||||||
# Build the URL
|
# Build the URL
|
||||||
if common.settings.get("public_mode"):
|
if mode_settings.get("general", "public"):
|
||||||
return f"http://{app.onion_host}"
|
return f"http://{app.onion_host}"
|
||||||
else:
|
else:
|
||||||
return f"http://onionshare:{web.password}@{app.onion_host}"
|
return f"http://onionshare:{web.password}@{app.onion_host}"
|
||||||
@ -56,32 +56,21 @@ def main(cwd=None):
|
|||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=28)
|
formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=28)
|
||||||
)
|
)
|
||||||
|
# Select modes
|
||||||
|
parser.add_argument(
|
||||||
|
"--receive", action="store_true", dest="receive", help="Receive files"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--website", action="store_true", dest="website", help="Publish website"
|
||||||
|
)
|
||||||
|
# Tor connection-related args
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--local-only",
|
"--local-only",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
dest="local_only",
|
dest="local_only",
|
||||||
|
default=False,
|
||||||
help="Don't use Tor (only for development)",
|
help="Don't use Tor (only for development)",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
|
||||||
"--stay-open",
|
|
||||||
action="store_true",
|
|
||||||
dest="stay_open",
|
|
||||||
help="Continue sharing after files have been sent",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--auto-start-timer",
|
|
||||||
metavar="<int>",
|
|
||||||
dest="autostart_timer",
|
|
||||||
default=0,
|
|
||||||
help="Schedule this share to start N seconds from now",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--auto-stop-timer",
|
|
||||||
metavar="<int>",
|
|
||||||
dest="autostop_timer",
|
|
||||||
default=0,
|
|
||||||
help="Stop sharing after a given amount of seconds",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--connect-timeout",
|
"--connect-timeout",
|
||||||
metavar="<int>",
|
metavar="<int>",
|
||||||
@ -89,30 +78,79 @@ def main(cwd=None):
|
|||||||
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(
|
|
||||||
"--stealth",
|
|
||||||
action="store_true",
|
|
||||||
dest="stealth",
|
|
||||||
help="Use client authorization (advanced)",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--receive",
|
|
||||||
action="store_true",
|
|
||||||
dest="receive",
|
|
||||||
help="Receive shares instead of sending them",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--website",
|
|
||||||
action="store_true",
|
|
||||||
dest="website",
|
|
||||||
help="Publish a static website",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--config",
|
"--config",
|
||||||
metavar="config",
|
metavar="config",
|
||||||
default=False,
|
default=None,
|
||||||
help="Custom JSON config file location (optional)",
|
help="Filename of custom global settings",
|
||||||
)
|
)
|
||||||
|
# Persistent file
|
||||||
|
parser.add_argument(
|
||||||
|
"--persistent",
|
||||||
|
metavar="persistent",
|
||||||
|
default=None,
|
||||||
|
help="Filename of persistent session",
|
||||||
|
)
|
||||||
|
# General args
|
||||||
|
parser.add_argument(
|
||||||
|
"--public",
|
||||||
|
action="store_true",
|
||||||
|
dest="public",
|
||||||
|
default=False,
|
||||||
|
help="Don't use a password",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--auto-start-timer",
|
||||||
|
metavar="<int>",
|
||||||
|
dest="autostart_timer",
|
||||||
|
default=0,
|
||||||
|
help="Start onion service at scheduled time (N seconds from now)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--auto-stop-timer",
|
||||||
|
metavar="<int>",
|
||||||
|
dest="autostop_timer",
|
||||||
|
default=0,
|
||||||
|
help="Stop onion service at schedule time (N seconds from now)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--legacy",
|
||||||
|
action="store_true",
|
||||||
|
dest="legacy",
|
||||||
|
default=False,
|
||||||
|
help="Use legacy address (v2 onion service, not recommended)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--client-auth",
|
||||||
|
action="store_true",
|
||||||
|
dest="client_auth",
|
||||||
|
default=False,
|
||||||
|
help="Use client authorization (requires --legacy)",
|
||||||
|
)
|
||||||
|
# Share args
|
||||||
|
parser.add_argument(
|
||||||
|
"--autostop-sharing",
|
||||||
|
action="store_true",
|
||||||
|
dest="autostop_sharing",
|
||||||
|
default=True,
|
||||||
|
help="Share files: Stop sharing after files have been sent",
|
||||||
|
)
|
||||||
|
# Receive args
|
||||||
|
parser.add_argument(
|
||||||
|
"--data-dir",
|
||||||
|
metavar="data_dir",
|
||||||
|
default=None,
|
||||||
|
help="Receive files: Save files received to this directory",
|
||||||
|
)
|
||||||
|
# Website args
|
||||||
|
parser.add_argument(
|
||||||
|
"--disable_csp",
|
||||||
|
action="store_true",
|
||||||
|
dest="disable_csp",
|
||||||
|
default=False,
|
||||||
|
help="Publish website: Disable Content Security Policy header (allows your website to use third-party resources)",
|
||||||
|
)
|
||||||
|
# Other
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-v",
|
"-v",
|
||||||
"--verbose",
|
"--verbose",
|
||||||
@ -132,16 +170,21 @@ def main(cwd=None):
|
|||||||
for i in range(len(filenames)):
|
for i in range(len(filenames)):
|
||||||
filenames[i] = os.path.abspath(filenames[i])
|
filenames[i] = os.path.abspath(filenames[i])
|
||||||
|
|
||||||
local_only = bool(args.local_only)
|
|
||||||
verbose = bool(args.verbose)
|
|
||||||
stay_open = bool(args.stay_open)
|
|
||||||
autostart_timer = int(args.autostart_timer)
|
|
||||||
autostop_timer = int(args.autostop_timer)
|
|
||||||
connect_timeout = int(args.connect_timeout)
|
|
||||||
stealth = bool(args.stealth)
|
|
||||||
receive = bool(args.receive)
|
receive = bool(args.receive)
|
||||||
website = bool(args.website)
|
website = bool(args.website)
|
||||||
|
local_only = bool(args.local_only)
|
||||||
|
connect_timeout = int(args.connect_timeout)
|
||||||
config = args.config
|
config = args.config
|
||||||
|
persistent = args.persistent
|
||||||
|
public = bool(args.public)
|
||||||
|
autostart_timer = int(args.autostart_timer)
|
||||||
|
autostop_timer = int(args.autostop_timer)
|
||||||
|
legacy = bool(args.legacy)
|
||||||
|
client_auth = bool(args.client_auth)
|
||||||
|
autostop_sharing = bool(args.autostop_sharing)
|
||||||
|
data_dir = args.data_dir
|
||||||
|
disable_csp = bool(args.disable_csp)
|
||||||
|
verbose = bool(args.verbose)
|
||||||
|
|
||||||
if receive:
|
if receive:
|
||||||
mode = "receive"
|
mode = "receive"
|
||||||
@ -169,6 +212,13 @@ def main(cwd=None):
|
|||||||
if not valid:
|
if not valid:
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
# client_auth can only be set if legacy is also set
|
||||||
|
if client_auth and not legacy:
|
||||||
|
print(
|
||||||
|
"Client authentication (--client-auth) is only supported with with legacy onion services (--legacy)"
|
||||||
|
)
|
||||||
|
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:
|
||||||
common.load_settings(config)
|
common.load_settings(config)
|
||||||
@ -180,6 +230,20 @@ def main(cwd=None):
|
|||||||
|
|
||||||
# Mode settings
|
# Mode settings
|
||||||
mode_settings = ModeSettings(common)
|
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
|
||||||
|
|
||||||
# Create the Web object
|
# Create the Web object
|
||||||
web = Web(common, False, mode_settings, mode)
|
web = Web(common, False, mode_settings, mode)
|
||||||
@ -202,36 +266,35 @@ def main(cwd=None):
|
|||||||
# Start the onionshare app
|
# Start the onionshare app
|
||||||
try:
|
try:
|
||||||
common.settings.load()
|
common.settings.load()
|
||||||
if not common.settings.get("public_mode"):
|
if not mode_settings.get("general", "public"):
|
||||||
web.generate_password(common.settings.get("password"))
|
web.generate_password(mode_settings.get("persistent", "password"))
|
||||||
else:
|
else:
|
||||||
web.password = None
|
web.password = None
|
||||||
app = OnionShare(common, onion, local_only, autostop_timer)
|
app = OnionShare(common, onion, local_only, autostop_timer)
|
||||||
app.set_stealth(stealth)
|
|
||||||
app.choose_port()
|
app.choose_port()
|
||||||
|
|
||||||
# Delay the startup if a startup timer was set
|
# Delay the startup if a startup timer was set
|
||||||
if autostart_timer > 0:
|
if autostart_timer > 0:
|
||||||
# Can't set a schedule that is later than the auto-stop timer
|
# Can't set a schedule that is later than the auto-stop timer
|
||||||
if app.autostop_timer > 0 and app.autostop_timer < autostart_timer:
|
if autostop_timer > 0 and autostop_timer < autostart_timer:
|
||||||
print(
|
print(
|
||||||
"The auto-stop time can't be the same or earlier than the auto-start time. Please update it to start sharing."
|
"The auto-stop time can't be the same or earlier than the auto-start time. Please update it to start sharing."
|
||||||
)
|
)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
app.start_onion_service(False, True)
|
app.start_onion_service(False, True)
|
||||||
url = build_url(common, 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":
|
||||||
print(
|
print(
|
||||||
f"Files sent to you appear in this folder: {common.settings.get('data_dir')}"
|
f"Files sent to you appear in this folder: {mode_settings.get('receive', 'data_dir')}"
|
||||||
)
|
)
|
||||||
print("")
|
print("")
|
||||||
print(
|
print(
|
||||||
"Warning: Receive mode lets people upload files to your computer. Some files can potentially take control of your computer if you open them. Only open things from people you trust, or if you know what you are doing."
|
"Warning: Receive mode lets people upload files to your computer. Some files can potentially take control of your computer if you open them. Only open things from people you trust, or if you know what you are doing."
|
||||||
)
|
)
|
||||||
print("")
|
print("")
|
||||||
if stealth:
|
if mode_settings.get("general", "client_auth"):
|
||||||
print(
|
print(
|
||||||
f"Give this address and HidServAuth lineto your sender, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}"
|
f"Give this address and HidServAuth lineto your sender, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}"
|
||||||
)
|
)
|
||||||
@ -241,7 +304,7 @@ def main(cwd=None):
|
|||||||
f"Give this address to your sender, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}"
|
f"Give this address to your sender, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if stealth:
|
if mode_settings.get("general", "client_auth"):
|
||||||
print(
|
print(
|
||||||
f"Give this address and HidServAuth line to your recipient, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}"
|
f"Give this address and HidServAuth line to your recipient, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}"
|
||||||
)
|
)
|
||||||
@ -291,10 +354,7 @@ def main(cwd=None):
|
|||||||
print("")
|
print("")
|
||||||
|
|
||||||
# Start OnionShare http service in new thread
|
# Start OnionShare http service in new thread
|
||||||
t = threading.Thread(
|
t = threading.Thread(target=web.start, args=(app.port,))
|
||||||
target=web.start,
|
|
||||||
args=(app.port, stay_open, common.settings.get("public_mode"), web.password),
|
|
||||||
)
|
|
||||||
t.daemon = True
|
t.daemon = True
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
@ -307,13 +367,13 @@ def main(cwd=None):
|
|||||||
app.autostop_timer_thread.start()
|
app.autostop_timer_thread.start()
|
||||||
|
|
||||||
# Save the web password if we are using a persistent private key
|
# Save the web password if we are using a persistent private key
|
||||||
if common.settings.get("save_private_key"):
|
if mode_settings.get("persistent", "enabled"):
|
||||||
if not common.settings.get("password"):
|
if not mode_settings.get("persistent", "password"):
|
||||||
common.settings.set("password", web.password)
|
mode_settings.set("persistent", "password", web.password)
|
||||||
common.settings.save()
|
# mode_settings.save()
|
||||||
|
|
||||||
# Build the URL
|
# Build the URL
|
||||||
url = build_url(common, app, web)
|
url = build_url(mode_settings, app, web)
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
if autostart_timer > 0:
|
if autostart_timer > 0:
|
||||||
@ -321,7 +381,7 @@ def main(cwd=None):
|
|||||||
else:
|
else:
|
||||||
if mode == "receive":
|
if mode == "receive":
|
||||||
print(
|
print(
|
||||||
f"Files sent to you appear in this folder: {common.settings.get('data_dir')}"
|
f"Files sent to you appear in this folder: {mode_settings.get('receive', 'data_dir')}"
|
||||||
)
|
)
|
||||||
print("")
|
print("")
|
||||||
print(
|
print(
|
||||||
@ -329,7 +389,7 @@ def main(cwd=None):
|
|||||||
)
|
)
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
if stealth:
|
if mode_settings.get("general", "client_auth"):
|
||||||
print("Give this address and HidServAuth to the sender:")
|
print("Give this address and HidServAuth to the sender:")
|
||||||
print(url)
|
print(url)
|
||||||
print(app.auth_string)
|
print(app.auth_string)
|
||||||
@ -337,7 +397,7 @@ def main(cwd=None):
|
|||||||
print("Give this address to the sender:")
|
print("Give this address to the sender:")
|
||||||
print(url)
|
print(url)
|
||||||
else:
|
else:
|
||||||
if stealth:
|
if mode_settings.get("general", "client_auth"):
|
||||||
print("Give this address and HidServAuth line to the recipient:")
|
print("Give this address and HidServAuth line to the recipient:")
|
||||||
print(url)
|
print(url)
|
||||||
print(app.auth_string)
|
print(app.auth_string)
|
||||||
|
@ -42,7 +42,6 @@ class OnionShare(object):
|
|||||||
self.hidserv_dir = None
|
self.hidserv_dir = None
|
||||||
self.onion_host = None
|
self.onion_host = None
|
||||||
self.port = None
|
self.port = None
|
||||||
self.stealth = None
|
|
||||||
|
|
||||||
# files and dirs to delete on shutdown
|
# files and dirs to delete on shutdown
|
||||||
self.cleanup_filenames = []
|
self.cleanup_filenames = []
|
||||||
@ -55,12 +54,6 @@ class OnionShare(object):
|
|||||||
# init auto-stop timer thread
|
# init auto-stop timer thread
|
||||||
self.autostop_timer_thread = None
|
self.autostop_timer_thread = None
|
||||||
|
|
||||||
def set_stealth(self, stealth):
|
|
||||||
self.common.log("OnionShare", f"set_stealth", "stealth={stealth}")
|
|
||||||
|
|
||||||
self.stealth = stealth
|
|
||||||
self.onion.stealth = stealth
|
|
||||||
|
|
||||||
def choose_port(self):
|
def choose_port(self):
|
||||||
"""
|
"""
|
||||||
Choose a random port.
|
Choose a random port.
|
||||||
|
@ -26,8 +26,7 @@ class SendBaseModeWeb:
|
|||||||
self.gzip_filesize = None
|
self.gzip_filesize = None
|
||||||
self.zip_writer = None
|
self.zip_writer = None
|
||||||
|
|
||||||
# If "Stop After First Download" is checked (stay_open == False), only allow
|
# If autostop_sharing, only allow one download at a time
|
||||||
# one download at a time.
|
|
||||||
self.download_in_progress = False
|
self.download_in_progress = False
|
||||||
|
|
||||||
# This tracks the history id
|
# This tracks the history id
|
||||||
|
@ -37,7 +37,10 @@ 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 = not self.web.stay_open and self.download_in_progress
|
deny_download = (
|
||||||
|
not self.web.settings.get("share", "autostop_sharing")
|
||||||
|
and self.download_in_progress
|
||||||
|
)
|
||||||
if deny_download:
|
if deny_download:
|
||||||
r = make_response(
|
r = make_response(
|
||||||
render_template("denied.html"),
|
render_template("denied.html"),
|
||||||
@ -60,7 +63,10 @@ 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 = not self.web.stay_open and self.download_in_progress
|
deny_download = (
|
||||||
|
not self.web.settings.get("share", "autostop_sharing")
|
||||||
|
and self.download_in_progress
|
||||||
|
)
|
||||||
if deny_download:
|
if deny_download:
|
||||||
r = make_response(
|
r = make_response(
|
||||||
render_template(
|
render_template(
|
||||||
@ -96,7 +102,7 @@ class ShareModeWeb(SendBaseModeWeb):
|
|||||||
|
|
||||||
def generate():
|
def generate():
|
||||||
# Starting a new download
|
# Starting a new download
|
||||||
if not self.web.stay_open:
|
if not 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
|
||||||
@ -161,11 +167,14 @@ class ShareModeWeb(SendBaseModeWeb):
|
|||||||
sys.stdout.write("\n")
|
sys.stdout.write("\n")
|
||||||
|
|
||||||
# Download is finished
|
# Download is finished
|
||||||
if not self.web.stay_open:
|
if not 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 not self.web.stay_open and not canceled:
|
if (
|
||||||
|
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:
|
||||||
|
@ -352,17 +352,11 @@ class Web:
|
|||||||
pass
|
pass
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
def start(self, port, stay_open=False, public_mode=False, password=None):
|
def start(self, port):
|
||||||
"""
|
"""
|
||||||
Start the flask web server.
|
Start the flask web server.
|
||||||
"""
|
"""
|
||||||
self.common.log(
|
self.common.log("Web", "start", f"port={port}")
|
||||||
"Web",
|
|
||||||
"start",
|
|
||||||
f"port={port}, stay_open={stay_open}, public_mode={public_mode}, password={password}",
|
|
||||||
)
|
|
||||||
|
|
||||||
self.stay_open = stay_open
|
|
||||||
|
|
||||||
# Make sure the stop_q is empty when starting a new server
|
# Make sure the stop_q is empty when starting a new server
|
||||||
while not self.stop_q.empty():
|
while not self.stop_q.empty():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user