diff options
Diffstat (limited to 'onionshare/__init__.py')
-rw-r--r-- | onionshare/__init__.py | 182 |
1 files changed, 122 insertions, 60 deletions
diff --git a/onionshare/__init__.py b/onionshare/__init__.py index 032b4acc..2f44c846 100644 --- a/onionshare/__init__.py +++ b/onionshare/__init__.py @@ -2,7 +2,7 @@ """ OnionShare | https://onionshare.org/ -Copyright (C) 2018 Micah Lee <micah@micahflee.com> +Copyright (C) 2014-2018 Micah Lee <micah@micahflee.com> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,21 +20,32 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. import os, sys, time, argparse, threading -from . import strings, common, web +from . import strings +from .common import Common +from .web import Web from .onion import * from .onionshare import OnionShare -from .settings import Settings def main(cwd=None): """ The main() function implements all of the logic that the command-line version of onionshare uses. """ + common = Common() + + # Load the default settings and strings early, for the sake of being able to parse options. + # These won't be in the user's chosen locale necessarily, but we need to parse them + # early in order to even display the option to pass alternate settings (which might + # contain a preferred locale). + # If an alternate --config is passed, we'll reload strings later. + common.load_settings() strings.load_strings(common) - print(strings._('version_string').format(common.get_version())) + + # Display OnionShare banner + print(strings._('version_string').format(common.version)) # OnionShare CLI in OSX needs to change current working directory (#132) - if common.get_platform() == 'Darwin': + if common.platform == 'Darwin': if cwd: os.chdir(cwd) @@ -44,9 +55,10 @@ def main(cwd=None): parser.add_argument('--stay-open', action='store_true', dest='stay_open', help=strings._("help_stay_open")) parser.add_argument('--shutdown-timeout', metavar='<int>', dest='shutdown_timeout', default=0, help=strings._("help_shutdown_timeout")) parser.add_argument('--stealth', action='store_true', dest='stealth', help=strings._("help_stealth")) - parser.add_argument('--debug', action='store_true', dest='debug', help=strings._("help_debug")) + parser.add_argument('--receive', action='store_true', dest='receive', help=strings._("help_receive")) parser.add_argument('--config', metavar='config', default=False, help=strings._('help_config')) - parser.add_argument('filename', metavar='filename', nargs='+', help=strings._('help_filename')) + parser.add_argument('--debug', action='store_true', dest='debug', help=strings._("help_debug")) + parser.add_argument('filename', metavar='filename', nargs='*', help=strings._('help_filename')) args = parser.parse_args() filenames = args.filename @@ -58,65 +70,86 @@ def main(cwd=None): stay_open = bool(args.stay_open) shutdown_timeout = int(args.shutdown_timeout) stealth = bool(args.stealth) + receive = bool(args.receive) config = args.config - # Debug mode? - if debug: - common.set_debug(debug) - web.debug_mode() - - # Validation - valid = True - for filename in filenames: - if not os.path.isfile(filename) and not os.path.isdir(filename): - print(strings._("not_a_file").format(filename)) - valid = False - if not os.access(filename, os.R_OK): - print(strings._("not_a_readable_file").format(filename)) - valid = False - if not valid: + if receive: + mode = 'receive' + else: + mode = 'share' + + # Make sure filenames given if not using receiver mode + if mode == 'share' and len(filenames) == 0: + parser.print_help() sys.exit() + # Validate filenames + if mode == 'share': + valid = True + for filename in filenames: + if not os.path.isfile(filename) and not os.path.isdir(filename): + print(strings._("not_a_file").format(filename)) + valid = False + if not os.access(filename, os.R_OK): + print(strings._("not_a_readable_file").format(filename)) + valid = False + if not valid: + sys.exit() + + # Re-load settings, if a custom config was passed in + if config: + common.load_settings(config) + # Re-load the strings, in case the provided config has changed locale + strings.load_strings(common) - settings = Settings(config) + # Debug mode? + common.debug = debug + + # Create the Web object + web = Web(common, False, mode) # Start the Onion object - onion = Onion() + onion = Onion(common) try: - onion.connect(settings=False, config=config) - except (TorTooOld, TorErrorInvalidSetting, TorErrorAutomatic, TorErrorSocketPort, TorErrorSocketFile, TorErrorMissingPassword, TorErrorUnreadableCookieFile, TorErrorAuthError, TorErrorProtocolError, BundledTorNotSupported, BundledTorTimeout) as e: - sys.exit(e.args[0]) + onion.connect(custom_settings=False, config=config) except KeyboardInterrupt: print("") sys.exit() + except Exception as e: + sys.exit(e.args[0]) # Start the onionshare app try: - app = OnionShare(onion, local_only, stay_open, shutdown_timeout) + app = OnionShare(common, onion, local_only, shutdown_timeout) app.set_stealth(stealth) + app.choose_port() app.start_onion_service() except KeyboardInterrupt: print("") sys.exit() + except (TorTooOld, TorErrorProtocolError) as e: + print("") + print(e.args[0]) + sys.exit() - # Prepare files to share - print(strings._("preparing_files")) - try: - web.set_file_info(filenames) - app.cleanup_filenames.append(web.zip_filename) - except OSError as e: - print(e.strerror) - sys.exit(1) - - # Warn about sending large files over Tor - if web.zip_filesize >= 157286400: # 150mb - print('') - print(strings._("large_filesize")) - print('') + if mode == 'share': + # Prepare files to share + print(strings._("preparing_files")) + try: + web.share_mode.set_file_info(filenames) + app.cleanup_filenames += web.share_mode.cleanup_filenames + except OSError as e: + print(e.strerror) + sys.exit(1) + + # Warn about sending large files over Tor + if web.share_mode.download_filesize >= 157286400: # 150mb + print('') + print(strings._("large_filesize")) + print('') # Start OnionShare http service in new thread - settings.load() - t = threading.Thread(target=web.start, args=(app.port, app.stay_open, settings.get('slug'))) + t = threading.Thread(target=web.start, args=(app.port, stay_open, common.settings.get('public_mode'), common.settings.get('slug'))) t.daemon = True t.start() @@ -129,18 +162,39 @@ def main(cwd=None): app.shutdown_timer.start() # Save the web slug if we are using a persistent private key - if settings.get('save_private_key'): - if not settings.get('slug'): - settings.set('slug', web.slug) - settings.save() - - if(stealth): - print(strings._("give_this_url_stealth")) - print('http://{0:s}/{1:s}'.format(app.onion_host, web.slug)) - print(app.auth_string) + if common.settings.get('save_private_key'): + if not common.settings.get('slug'): + common.settings.set('slug', web.slug) + common.settings.save() + + # Build the URL + if common.settings.get('public_mode'): + url = 'http://{0:s}'.format(app.onion_host) + else: + url = 'http://{0:s}/{1:s}'.format(app.onion_host, web.slug) + + print('') + if mode == 'receive': + print(strings._('receive_mode_data_dir').format(common.settings.get('data_dir'))) + print('') + print(strings._('receive_mode_warning')) + print('') + + if stealth: + print(strings._("give_this_url_receive_stealth")) + print(url) + print(app.auth_string) + else: + print(strings._("give_this_url_receive")) + print(url) else: - print(strings._("give_this_url")) - print('http://{0:s}/{1:s}'.format(app.onion_host, web.slug)) + if stealth: + print(strings._("give_this_url_stealth")) + print(url) + print(app.auth_string) + else: + print(strings._("give_this_url")) + print(url) print('') print(strings._("ctrlc_to_stop")) @@ -149,11 +203,19 @@ def main(cwd=None): if app.shutdown_timeout > 0: # if the shutdown timer was set and has run out, stop the server if not app.shutdown_timer.is_alive(): - # If there were no attempts to download the share, or all downloads are done, we can stop - if web.download_count == 0 or web.done: - print(strings._("close_on_timeout")) - web.stop(app.port) - break + if mode == 'share': + # If there were no attempts to download the share, or all downloads are done, we can stop + if web.share_mode.download_count == 0 or web.done: + print(strings._("close_on_timeout")) + web.stop(app.port) + break + if mode == 'receive': + if web.receive_mode.upload_count == 0 or not web.receive_mode.uploads_in_progress: + print(strings._("close_on_timeout")) + web.stop(app.port) + break + else: + web.receive_mode.can_upload = False # Allow KeyboardInterrupt exception to be handled with threads # https://stackoverflow.com/questions/3788208/python-threading-ignores-keyboardinterrupt-exception time.sleep(0.2) |