def _compute_total_size(filenames): total_size = 0 for filename in filenames: if os.path.isfile(filename): total_size += os.path.getsize(filename) if os.path.isdir(filename): total_size += Common.dir_size(filename) return total_size
def setUpClass(cls): common = Common(verbose=True) # Delete any old test data that might exist shutil.rmtree(common.build_data_dir(), ignore_errors=True) qtapp = Application(common) common.gui = GuiCommon(common, qtapp, local_only=True) cls.gui = MainWindow(common, filenames=None) cls.gui.qtapp = qtapp # Create some random files to test with cls.tmpdir = tempfile.TemporaryDirectory() cls.tmpfiles = [] for _ in range(10): filename = os.path.join(cls.tmpdir.name, f"{secrets.token_hex(4)}.txt") with open(filename, "w") as file: file.write(secrets.token_hex(10)) cls.tmpfiles.append(filename) # A file called "test.txt" cls.tmpfile_test = os.path.join(cls.tmpdir.name, "test.txt") with open(cls.tmpfile_test, "w") as file: file.write("onionshare") # A file called "test2.txt" cls.tmpfile_test2 = os.path.join(cls.tmpdir.name, "test2.txt") with open(cls.tmpfile_test2, "w") as file: file.write("onionshare2") # A file called "index.html" cls.tmpfile_index_html = os.path.join(cls.tmpdir.name, "index.html") with open(cls.tmpfile_index_html, "w") as file: file.write( "<html><body><p>This is a test website hosted by OnionShare</p></body></html>" ) # A large file size = 1024 * 1024 * 155 cls.tmpfile_large = os.path.join(cls.tmpdir.name, "large_file") with open(cls.tmpfile_large, "wb") as fout: fout.write(os.urandom(size))
class TestZipWriterCustom: @pytest.mark.parametrize( "test_input", (Common.random_string(random.randint(2, 50), random.choice((None, random.randint(2, 50)))) for _ in range(50)), ) def test_random_string_regex(self, test_input): assert bool(RANDOM_STR_REGEX.match(test_input)) def test_custom_filename(self, custom_zw): assert bool(RANDOM_STR_REGEX.match(custom_zw.zip_filename)) def test_custom_callback(self, custom_zw): assert custom_zw.processed_size_callback(None) == "custom_callback"
def qWait(t, qtapp): end = datetime.now() + timedelta(milliseconds=t) while datetime.now() < end: qtapp.processEvents() # Monkeypatch qWait, because PySide2 doesn't have it # https://stackoverflow.com/questions/17960159/qwait-analogue-in-pyside QtTest.QTest.qWait = qWait # Allow importing onionshare_cli from the source tree sys.path.insert( 0, os.path.join( os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "cli", ), ) # Create common and qtapp singletons from onionshare_cli.common import Common from onionshare import Application common = Common(verbose=True) qtapp = Application(common) # Attach them to sys, so GuiBaseTest can retrieve them sys.onionshare_common = common sys.onionshare_qtapp = qtapp
def main(): """ The main() function implements all of the logic that the GUI version of onionshare uses. """ common = Common() # Required for macOS Big Sur: https://stackoverflow.com/a/64878899 if common.platform == "Darwin": os.environ["QT_MAC_WANTS_LAYER"] = "1" # Display OnionShare banner print(f"OnionShare {common.version} | https://onionshare.org/") # Start the Qt app global qtapp qtapp = Application(common) # Parse arguments parser = argparse.ArgumentParser(formatter_class=lambda prog: argparse. HelpFormatter(prog, max_help_position=48)) parser.add_argument( "--local-only", action="store_true", dest="local_only", help="Don't use Tor (only for development)", ) parser.add_argument( "-v", "--verbose", action="store_true", dest="verbose", help="Log OnionShare errors to stdout, and web errors to disk", ) parser.add_argument( "--filenames", metavar="filenames", nargs="+", help="List of files or folders to share", ) args = parser.parse_args() filenames = args.filenames if filenames: for i in range(len(filenames)): filenames[i] = os.path.abspath(filenames[i]) local_only = bool(args.local_only) verbose = bool(args.verbose) # Verbose mode? common.verbose = verbose # Attach the GUI common parts to the common object common.gui = GuiCommon(common, qtapp, local_only) # Validation if filenames: valid = True for filename in filenames: if not os.path.isfile(filename) and not os.path.isdir(filename): Alert(common, f"{filename} is not a valid file.") valid = False if not os.access(filename, os.R_OK): Alert(common, f"{filename} is not a readable file.") valid = False if not valid: sys.exit() # Is there another onionshare-gui running? if os.path.exists(common.gui.lock_filename): with open(common.gui.lock_filename, "r") as f: existing_pid = int(f.read()) # Is this process actually still running? still_running = True if not psutil.pid_exists(existing_pid): still_running = False else: for proc in psutil.process_iter(["pid", "name", "username"]): if proc.pid == existing_pid: if (proc.username() != getpass.getuser() or "onionshare" not in " ".join(proc.cmdline()).lower()): still_running = False if still_running: print( f"Opening tab in existing OnionShare window (pid {existing_pid})" ) # Make an event for the existing OnionShare window if filenames: obj = {"type": "new_share_tab", "filenames": filenames} else: obj = {"type": "new_tab"} # Write that event to disk with open(common.gui.events_filename, "a") as f: f.write(json.dumps(obj) + "\n") return else: os.remove(common.gui.lock_filename) # Write the lock file with open(common.gui.lock_filename, "w") as f: f.write(f"{os.getpid()}\n") # Allow Ctrl-C to smoothly quit the program instead of throwing an exception def signal_handler(s, frame): print("\nCtrl-C pressed, quitting") if os.path.exists(common.gui.lock_filename): os.remove(common.gui.lock_filename) sys.exit(0) signal.signal(signal.SIGINT, signal_handler) # Launch the gui main_window = MainWindow(common, filenames) # If filenames were passed in, open them in a tab if filenames: main_window.tabs.new_share_tab(filenames) # Clean up when app quits def shutdown(): main_window.cleanup() os.remove(common.gui.lock_filename) qtapp.aboutToQuit.connect(shutdown) # All done sys.exit(qtapp.exec_())
def mode_settings_obj(): common = Common() return ModeSettings(common)
def onionshare_obj(): common = Common() return OnionShare(common, MyOnion())