diff --git a/.circleci/config.yml b/.circleci/config.yml index dd84e371..67d8ab0e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -36,7 +36,7 @@ jobs: name: Install dependencies command: | sudo apt-get update - sudo apt-get install -y python3-pip xvfb + sudo apt-get install -y python3-pip xvfb tor obfs4proxy sudo pip3 install poetry flake8 poetry install diff --git a/BUILD.md b/BUILD.md index 346a6f43..da38590f 100644 --- a/BUILD.md +++ b/BUILD.md @@ -32,7 +32,7 @@ cd onionshare The recommended way to develop OnionShare is to use the latest versions of all dependencies. -First, install `tor` from either the [official Debian repository](https://support.torproject.org/apt/tor-deb-repo/), or from your package manager. +First, install `tor` and `obfs4proxy` from either the [official Debian repository](https://support.torproject.org/apt/tor-deb-repo/), or from your package manager. Then download Qt 5.14.0 for Linux: @@ -300,6 +300,7 @@ Before making a release, all of these should be complete: * `share/version.txt` should have the correct version * `pyproject.toml` should have the correct version +* `install/org.onionshare.OnionShare.appdata.xml` should have the correct version * `install/onionshare.nsi` should have the correct version, for the Windows installer * `CHANGELOG.md` should be updated to include a list of all major changes since the last release * There must be a PGP-signed git tag for the version, e.g. for OnionShare 2.1, the tag must be `v2.1` diff --git a/install/org.onionshare.OnionShare.appdata.xml b/install/org.onionshare.OnionShare.appdata.xml index 6ae1b5b6..c9a0b11c 100644 --- a/install/org.onionshare.OnionShare.appdata.xml +++ b/install/org.onionshare.OnionShare.appdata.xml @@ -8,17 +8,10 @@ Securely and anonymously share a file of any size

- OnionShare lets you securely and anonymously send and receive files. It works by starting a web server, - making it accessible as a Tor onion service, and generating an unguessable web address so others can - download files from you, or upload files to you. It does not require setting up a separate server - or using a third party file-sharing service. + OnionShare lets you securely and anonymously send and receive files. It works by starting a web server, making it accessible as a Tor onion service, and generating an unguessable web address so others can download files from you, or upload files to you. It does not require setting up a separate server or using a third party file-sharing service.

- If you want to send files to someone, OnionShare hosts them on your own computer and uses a Tor onion - service to make them temporarily accessible over the internet. The receiving user just needs to open the web - address in Tor Browser to download the files. If you want to receive files, OnionShare hosts an anonymous - dropbox directly on your computer and uses a Tor onion service to make it temporarily accessible over the - internet. Other users can upload files to you from by loading the web address in Tor Browser. + If you want to send files to someone, OnionShare hosts them on your own computer and uses a Tor onion service to make them temporarily accessible over the internet. The receiving user just needs to open the web address in Tor Browser to download the files. If you want to receive files, OnionShare hosts an anonymous dropbox directly on your computer and uses a Tor onion service to make it temporarily accessible over the internet. Other users can upload files to you from by loading the web address in Tor Browser.

org.onionshare.OnionShare.desktop @@ -47,6 +40,6 @@ micah@micahflee.com - + diff --git a/install/org.onionshare.OnionShare.desktop b/install/org.onionshare.OnionShare.desktop index 02592a72..190e2f26 100644 --- a/install/org.onionshare.OnionShare.desktop +++ b/install/org.onionshare.OnionShare.desktop @@ -5,7 +5,7 @@ Comment=Share a file securely and anonymously over Tor Comment[da]=Del en fil sikkert og anonymt over Tor Comment[de]=Teile Dateien sicher und anonym über das Tor-Netzwerk Comment[hr]=Dijeli datoteku sigurno i anonimno preko Tora -Exec=/usr/bin/onionshare-gui +Exec=onionshare-gui Terminal=false Type=Application Icon=org.onionshare.OnionShare diff --git a/install/org.onionshare.OnionShare.png b/install/org.onionshare.OnionShare.png new file mode 100644 index 00000000..a4810d04 Binary files /dev/null and b/install/org.onionshare.OnionShare.png differ diff --git a/onionshare/common.py b/onionshare/common.py index 7048c174..b74534ff 100644 --- a/onionshare/common.py +++ b/onionshare/common.py @@ -28,6 +28,7 @@ import sys import tempfile import threading import time +import shutil from .settings import Settings @@ -97,8 +98,12 @@ class Common: ) elif self.platform == "BSD" or self.platform == "Linux": - # Assume OnionShare is installed systemwide in Linux, since we're not running in dev mode - prefix = os.path.join(sys.prefix, "share/onionshare") + # Look for resources relative to the binary, so if the binary is /usr/bin/onionshare-gui and + # the resource dir is /usr/share/onionshare, then the resource dir relative to the binary dir + # is ../share/onionshare + prefix = os.path.join( + os.path.dirname(os.path.dirname(sys.argv[0])), "share/onionshare" + ) elif getattr(sys, "frozen", False): # Check if app is "frozen" @@ -112,10 +117,11 @@ class Common: def get_tor_paths(self): if self.platform == "Linux": - tor_path = "/usr/bin/tor" - tor_geo_ip_file_path = "/usr/share/tor/geoip" - tor_geo_ipv6_file_path = "/usr/share/tor/geoip6" - obfs4proxy_file_path = "/usr/bin/obfs4proxy" + tor_path = shutil.which("tor") + obfs4proxy_file_path = shutil.which("obfs4proxy") + prefix = os.path.dirname(os.path.dirname(tor_path)) + tor_geo_ip_file_path = os.path.join(prefix, "share/tor/geoip") + tor_geo_ipv6_file_path = os.path.join(prefix, "share/tor/geoip6") elif self.platform == "Windows": base_path = os.path.join( os.path.dirname(os.path.dirname(self.get_resource_path(""))), "tor" diff --git a/onionshare_gui/__init__.py b/onionshare_gui/__init__.py index f0186a18..d083f741 100644 --- a/onionshare_gui/__init__.py +++ b/onionshare_gui/__init__.py @@ -24,7 +24,6 @@ import platform import argparse import signal import json -import psutil from PyQt5 import QtCore, QtWidgets from onionshare.common import Common @@ -65,10 +64,6 @@ def main(): # Display OnionShare banner print(f"OnionShare {common.version} | https://onionshare.org/") - # Allow Ctrl-C to smoothly quit the program instead of throwing an exception - # https://stackoverflow.com/questions/42814093/how-to-handle-ctrlc-in-python-app-with-pyqt - signal.signal(signal.SIGINT, signal.SIG_DFL) - # Start the Qt app global qtapp qtapp = Application(common) @@ -126,27 +121,11 @@ def main(): sys.exit() # Is there another onionshare-gui running? - existing_pid = None - for proc in psutil.process_iter(attrs=["pid", "name", "cmdline"]): - if proc.info["pid"] == os.getpid(): - continue + if os.path.exists(common.gui.lock_filename): + with open(common.gui.lock_filename, "r") as f: + existing_pid = int(f.read()) - if proc.info["name"] == "onionshare-gui" and proc.status() != "zombie": - existing_pid = proc.info["pid"] - break - else: - # Dev mode onionshare? - if proc.info["cmdline"] and len(proc.info["cmdline"]) >= 2: - if ( - os.path.basename(proc.info["cmdline"][0]).lower() == "python" - and os.path.basename(proc.info["cmdline"][1]) == "onionshare-gui" - and proc.status() != "zombie" - ): - existing_pid = proc.info["pid"] - break - - if existing_pid: - print(f"Opening tab in existing OnionShare window (pid {proc.info['pid']})") + print(f"Opening tab in existing OnionShare window (pid {existing_pid})") # Make an event for the existing OnionShare window if filenames: @@ -159,6 +138,20 @@ def main(): f.write(json.dumps(obj) + "\n") return + else: + # 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) @@ -169,6 +162,7 @@ def main(): # Clean up when app quits def shutdown(): main_window.cleanup() + os.remove(common.gui.lock_filename) qtapp.aboutToQuit.connect(shutdown) diff --git a/onionshare_gui/event_handler.py b/onionshare_gui/event_handler.py deleted file mode 100644 index f4d10c24..00000000 --- a/onionshare_gui/event_handler.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- -""" -OnionShare | https://onionshare.org/ - -Copyright (C) 2014-2018 Micah Lee - -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 -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -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 json -import os -from watchdog.observers import Observer -from watchdog.events import FileSystemEventHandler, FileModifiedEvent -from PyQt5 import QtCore - - -class EventHandler(FileSystemEventHandler, QtCore.QObject): - """ - To trigger an event, write a JSON line to the events file. When that file changes, - each line will be handled as an event. Valid events are: - {"type": "new_tab"} - {"type": "new_share_tab", "filenames": ["file1", "file2"]} - """ - - new_tab = QtCore.pyqtSignal() - new_share_tab = QtCore.pyqtSignal(list) - - def __init__(self, common): - super(EventHandler, self).__init__() - self.common = common - - def on_modified(self, event): - if ( - type(event) == FileModifiedEvent - and event.src_path == self.common.gui.events_filename - ): - # Read all the lines in the events, then delete it - with open(self.common.gui.events_filename, "r") as f: - lines = f.readlines() - os.remove(self.common.gui.events_filename) - - self.common.log( - "EventHandler", "on_modified", f"processing {len(lines)} lines" - ) - for line in lines: - try: - obj = json.loads(line) - if "type" not in obj: - self.common.log( - "EventHandler", - "on_modified", - f"event does not have a type: {obj}", - ) - continue - except json.decoder.JSONDecodeError: - self.common.log( - "EventHandler", "on_modified", f"ignoring invalid line: {line}" - ) - continue - - if obj["type"] == "new_tab": - self.common.log("EventHandler", "on_modified", "new_tab event") - self.new_tab.emit() - - elif obj["type"] == "new_share_tab": - if "filenames" in obj and type(obj["filenames"]) is list: - self.new_share_tab.emit(obj["filenames"]) - else: - self.common.log( - "EventHandler", - "on_modified", - f"invalid new_share_tab event: {obj}", - ) - - else: - self.common.log( - "EventHandler", "on_modified", f"invalid event type: {obj}" - ) - diff --git a/onionshare_gui/gui_common.py b/onionshare_gui/gui_common.py index 40c912bb..eb259301 100644 --- a/onionshare_gui/gui_common.py +++ b/onionshare_gui/gui_common.py @@ -37,6 +37,9 @@ class GuiCommon: self.qtapp = qtapp self.local_only = local_only + # Are we running in a flatpak package? + self.is_flatpak = os.path.exists("/.flatpak-info") + # Load settings self.common.load_settings() @@ -46,7 +49,10 @@ class GuiCommon: # Start the Onion self.onion = Onion(common) - # Directory to watch for events + # Lock filename + self.lock_filename = os.path.join(self.common.build_data_dir(), "lock") + + # Events filenames self.events_dir = os.path.join(self.common.build_data_dir(), "events") if not os.path.exists(self.events_dir): os.makedirs(self.events_dir, 0o700, True) diff --git a/onionshare_gui/settings_dialog.py b/onionshare_gui/settings_dialog.py index 45eef270..f8cb4204 100644 --- a/onionshare_gui/settings_dialog.py +++ b/onionshare_gui/settings_dialog.py @@ -142,7 +142,9 @@ class SettingsDialog(QtWidgets.QDialog): self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path, ) = self.common.get_tor_paths() - if not os.path.isfile(self.obfs4proxy_file_path): + if not self.obfs4proxy_file_path or not os.path.isfile( + self.obfs4proxy_file_path + ): self.tor_bridges_use_obfs4_radio = QtWidgets.QRadioButton( strings._("gui_settings_tor_bridges_obfs4_radio_option_no_obfs4proxy") ) @@ -163,7 +165,9 @@ class SettingsDialog(QtWidgets.QDialog): self.tor_geo_ipv6_file_path, self.obfs4proxy_file_path, ) = self.common.get_tor_paths() - if not os.path.isfile(self.obfs4proxy_file_path): + if not self.obfs4proxy_file_path or not os.path.isfile( + self.obfs4proxy_file_path + ): self.tor_bridges_use_meek_lite_azure_radio = QtWidgets.QRadioButton( strings._( "gui_settings_tor_bridges_meek_lite_azure_radio_option_no_obfs4proxy" @@ -662,8 +666,7 @@ class SettingsDialog(QtWidgets.QDialog): onion = Onion(self.common, use_tmp_dir=True) onion.connect( - custom_settings=settings, - tor_status_update_func=tor_status_update_func, + custom_settings=settings, tor_status_update_func=tor_status_update_func, ) # If an exception hasn't been raised yet, the Tor settings work @@ -750,9 +753,7 @@ class SettingsDialog(QtWidgets.QDialog): ) close_forced_update_thread() - forced_update_thread = UpdateThread( - self.common, self.onion, force=True - ) + forced_update_thread = UpdateThread(self.common, self.onion, force=True) forced_update_thread.update_available.connect(update_available) forced_update_thread.update_not_available.connect(update_not_available) forced_update_thread.update_error.connect(update_error) @@ -850,7 +851,10 @@ class SettingsDialog(QtWidgets.QDialog): f"Onion done rebooting, connected to Tor: {self.common.gui.onion.connected_to_tor}", ) - if self.common.gui.onion.is_authenticated() and not tor_con.wasCanceled(): + if ( + self.common.gui.onion.is_authenticated() + and not tor_con.wasCanceled() + ): self.settings_saved.emit() self.close() @@ -866,7 +870,10 @@ class SettingsDialog(QtWidgets.QDialog): Cancel button clicked. """ self.common.log("SettingsDialog", "cancel_clicked") - if not self.common.gui.local_only and not self.common.gui.onion.is_authenticated(): + if ( + not self.common.gui.local_only + and not self.common.gui.onion.is_authenticated() + ): Alert( self.common, strings._("gui_tor_connection_canceled"), diff --git a/onionshare_gui/tab/mode/history.py b/onionshare_gui/tab/mode/history.py index f445efa6..c1a2d54d 100644 --- a/onionshare_gui/tab/mode/history.py +++ b/onionshare_gui/tab/mode/history.py @@ -250,11 +250,11 @@ class ReceiveHistoryItemFile(QtWidgets.QWidget): if self.common.platform == "Linux" or self.common.platform == "BSD": try: # If nautilus is available, open it - subprocess.Popen(["nautilus", abs_filename]) + subprocess.Popen(["xdg-open", self.dir]) except: Alert( self.common, - strings._("gui_open_folder_error_nautilus").format(abs_filename), + strings._("gui_open_folder_error").format(abs_filename), ) # macOS diff --git a/onionshare_gui/tab/mode/receive_mode/__init__.py b/onionshare_gui/tab/mode/receive_mode/__init__.py index ba1fc8c4..92cd17fa 100644 --- a/onionshare_gui/tab/mode/receive_mode/__init__.py +++ b/onionshare_gui/tab/mode/receive_mode/__init__.py @@ -17,6 +17,7 @@ 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 from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings @@ -24,7 +25,7 @@ from onionshare.web import Web from ..history import History, ToggleHistory, ReceiveHistoryItem from .. import Mode -from ....widgets import MinimumWidthWidget +from ....widgets import MinimumWidthWidget, Alert class ReceiveMode(Mode): @@ -135,6 +136,12 @@ class ReceiveMode(Mode): ) if selected_dir: + # If we're running inside a flatpak package, the data dir must be inside ~/OnionShare + if self.common.gui.is_flatpak: + if not selected_dir.startswith(os.path.expanduser("~/OnionShare")): + Alert(self.common, strings._("gui_receive_flatpak_data_dir")) + return + self.common.log( "ReceiveMode", "data_dir_button_clicked", diff --git a/onionshare_gui/tab_widget.py b/onionshare_gui/tab_widget.py index df4072f3..1ef82cad 100644 --- a/onionshare_gui/tab_widget.py +++ b/onionshare_gui/tab_widget.py @@ -18,13 +18,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ from PyQt5 import QtCore, QtWidgets, QtGui -from watchdog.observers import Observer from onionshare import strings from onionshare.mode_settings import ModeSettings from .tab import Tab -from .event_handler import EventHandler +from .threads import EventHandlerThread class TabWidget(QtWidgets.QTabWidget): @@ -73,17 +72,16 @@ class TabWidget(QtWidgets.QTabWidget): self.move_new_tab_button() # Watch the events file for changes - self.event_handler = EventHandler(common) - self.event_handler.new_tab.connect(self.add_tab) - self.event_handler.new_share_tab.connect(self.new_share_tab) - self.observer = Observer() - self.observer.schedule(self.event_handler, self.common.gui.events_dir) - self.observer.start() + self.event_handler_t = EventHandlerThread(common) + self.event_handler_t.new_tab.connect(self.add_tab) + self.event_handler_t.new_share_tab.connect(self.new_share_tab) + self.event_handler_t.start() def cleanup(self): # Stop the event thread - self.observer.stop() - self.observer.join() + self.event_handler_t.should_quit = True + self.event_handler_t.quit() + self.event_handler_t.wait(50) # Clean up each tab for index in range(self.count()): diff --git a/onionshare_gui/threads.py b/onionshare_gui/threads.py index 785e6ece..29554039 100644 --- a/onionshare_gui/threads.py +++ b/onionshare_gui/threads.py @@ -18,6 +18,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . """ import time +import json +import os from PyQt5 import QtCore from onionshare import strings @@ -166,3 +168,85 @@ class AutoStartTimer(QtCore.QThread): except ValueError as e: self.error.emit(e.args[0]) return + + +class EventHandlerThread(QtCore.QThread): + """ + To trigger an event, write a JSON line to the events file. When that file changes, + each line will be handled as an event. Valid events are: + {"type": "new_tab"} + {"type": "new_share_tab", "filenames": ["file1", "file2"]} + """ + + new_tab = QtCore.pyqtSignal() + new_share_tab = QtCore.pyqtSignal(list) + + def __init__(self, common): + super(EventHandlerThread, self).__init__() + self.common = common + self.common.log("EventHandlerThread", "__init__") + self.should_quit = False + + def run(self): + self.common.log("EventHandlerThread", "run") + + mtime = 0 + while True: + if os.path.exists(self.common.gui.events_filename): + # Events file exists + if os.stat(self.common.gui.events_filename).st_mtime != mtime: + # Events file has been modified, load events + try: + with open(self.common.gui.events_filename, "r") as f: + lines = f.readlines() + os.remove(self.common.gui.events_filename) + + self.common.log( + "EventHandler", "run", f"processing {len(lines)} lines" + ) + for line in lines: + try: + obj = json.loads(line) + if "type" not in obj: + self.common.log( + "EventHandler", + "run", + f"event does not have a type: {obj}", + ) + continue + except json.decoder.JSONDecodeError: + self.common.log( + "EventHandler", + "run", + f"ignoring invalid line: {line}", + ) + continue + + if obj["type"] == "new_tab": + self.common.log("EventHandler", "run", "new_tab event") + self.new_tab.emit() + + elif obj["type"] == "new_share_tab": + if ( + "filenames" in obj + and type(obj["filenames"]) is list + ): + self.new_share_tab.emit(obj["filenames"]) + else: + self.common.log( + "EventHandler", + "run", + f"invalid new_share_tab event: {obj}", + ) + + else: + self.common.log( + "EventHandler", "run", f"invalid event type: {obj}" + ) + + except: + pass + + if self.should_quit: + break + time.sleep(0.2) diff --git a/onionshare_gui/tor_connection_dialog.py b/onionshare_gui/tor_connection_dialog.py index 37c0ebc3..9c17e65c 100644 --- a/onionshare_gui/tor_connection_dialog.py +++ b/onionshare_gui/tor_connection_dialog.py @@ -157,10 +157,8 @@ class TorConnectionThread(QtCore.QThread): self.canceled_connecting_to_tor.emit() except Exception as e: - self.common.log( - "TorConnectionThread", "run", f"caught exception: {e.args[0]}" - ) - self.error_connecting_to_tor.emit(str(e.args[0])) + self.common.log("TorConnectionThread", "run", f"caught exception: {e}") + self.error_connecting_to_tor.emit(str(e)) def _tor_status_update(self, progress, summary): self.tor_status_update.emit(progress, summary) diff --git a/poetry.lock b/poetry.lock index b3ac93b3..185428e1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -12,7 +12,7 @@ description = "Atomic file writes." name = "atomicwrites" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.0" +version = "1.4.0" [[package]] category = "dev" @@ -34,7 +34,7 @@ description = "Python package for providing Mozilla's CA Bundle." name = "certifi" optional = false python-versions = "*" -version = "2019.11.28" +version = "2020.6.20" [[package]] category = "main" @@ -50,7 +50,7 @@ description = "Composable command line interface toolkit" name = "click" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "7.1.1" +version = "7.1.2" [[package]] category = "main" @@ -76,7 +76,7 @@ description = "A simple framework for building complex web applications." name = "flask" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "1.1.1" +version = "1.1.2" [package.dependencies] Jinja2 = ">=2.10.1" @@ -95,7 +95,7 @@ description = "Basic and Digest HTTP authentication for Flask routes" name = "flask-httpauth" optional = false python-versions = "*" -version = "3.3.0" +version = "4.1.0" [package.dependencies] Flask = "*" @@ -114,7 +114,7 @@ description = "Internationalized Domain Names in Applications (IDNA)" name = "idna" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.9" +version = "2.10" [[package]] category = "dev" @@ -123,14 +123,14 @@ marker = "python_version < \"3.8\"" name = "importlib-metadata" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -version = "1.5.0" +version = "1.7.0" [package.dependencies] zipp = ">=0.5" [package.extras] docs = ["sphinx", "rst.linker"] -testing = ["packaging", "importlib-resources"] +testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] [[package]] category = "main" @@ -146,7 +146,7 @@ description = "A very fast and expressive template engine." name = "jinja2" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.11.1" +version = "2.11.2" [package.dependencies] MarkupSafe = ">=0.23" @@ -179,7 +179,7 @@ description = "More routines for operating on iterables, beyond itertools" name = "more-itertools" optional = false python-versions = ">=3.5" -version = "8.2.0" +version = "8.4.0" [[package]] category = "dev" @@ -187,20 +187,12 @@ description = "Core utilities for Python packages" name = "packaging" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.3" +version = "20.4" [package.dependencies] pyparsing = ">=2.0.2" six = "*" -[[package]] -category = "main" -description = "File system general utilities" -name = "pathtools" -optional = false -python-versions = "*" -version = "0.1.2" - [[package]] category = "main" description = "Python PE parsing module" @@ -228,24 +220,13 @@ version = ">=0.12" [package.extras] dev = ["pre-commit", "tox"] -[[package]] -category = "main" -description = "Cross-platform lib for process and system monitoring in Python." -name = "psutil" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "5.7.0" - -[package.extras] -enum = ["enum34"] - [[package]] category = "dev" description = "library with cross-python path, ini-parsing, io, code, log facilities" name = "py" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.8.1" +version = "1.9.0" [[package]] category = "main" @@ -253,7 +234,7 @@ description = "Cryptographic library for Python" name = "pycryptodome" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.9.7" +version = "3.9.8" [[package]] category = "dev" @@ -275,7 +256,7 @@ description = "Python parsing module" name = "pyparsing" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.4.6" +version = "2.4.7" [[package]] category = "main" @@ -294,7 +275,7 @@ description = "The sip module support for PyQt5" name = "pyqt5-sip" optional = false python-versions = ">=3.5" -version = "12.7.1" +version = "12.8.0" [[package]] category = "main" @@ -310,7 +291,7 @@ description = "pytest: simple powerful testing with Python" name = "pytest" optional = false python-versions = ">=3.5" -version = "5.4.1" +version = "5.4.3" [package.dependencies] atomicwrites = ">=1.0" @@ -380,7 +361,7 @@ description = "Python HTTP for Humans." name = "requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.23.0" +version = "2.24.0" [package.dependencies] certifi = ">=2017.4.17" @@ -398,7 +379,7 @@ description = "Python 2 and 3 compatibility utilities" name = "six" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -version = "1.14.0" +version = "1.15.0" [[package]] category = "main" @@ -414,34 +395,20 @@ description = "HTTP library with thread-safe connection pooling, file post, and name = "urllib3" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "1.25.8" +version = "1.25.9" [package.extras] brotli = ["brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] -[[package]] -category = "main" -description = "Filesystem events monitoring" -name = "watchdog" -optional = false -python-versions = "*" -version = "0.10.2" - -[package.dependencies] -pathtools = ">=0.1.1" - -[package.extras] -watchmedo = ["PyYAML (>=3.10)", "argh (>=0.24.1)"] - [[package]] category = "dev" -description = "Measures number of Terminal column cells of wide-character codes" +description = "Measures the displayed width of unicode strings in a terminal" name = "wcwidth" optional = false python-versions = "*" -version = "0.1.8" +version = "0.2.5" [[package]] category = "main" @@ -449,10 +416,10 @@ description = "The comprehensive WSGI web application library." name = "werkzeug" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "1.0.0" +version = "1.0.1" [package.extras] -dev = ["pytest", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinx-issues"] +dev = ["pytest", "pytest-timeout", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinx-issues"] watchdog = ["watchdog"] [[package]] @@ -469,7 +436,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["jaraco.itertools", "func-timeout"] [metadata] -content-hash = "3f46cfec01bcb5166c9f354aaf4439064b477955f3ea2373fcfdb65d5b89276e" +content-hash = "71c32a60a36f2e66745f800f5cab96e8d2551f5959acc8b07aa9003d6f3f702b" python-versions = "^3.7" [metadata.files] @@ -478,24 +445,24 @@ altgraph = [ {file = "altgraph-0.17.tar.gz", hash = "sha256:1f05a47122542f97028caf78775a095fbe6a2699b5089de8477eb583167d69aa"}, ] atomicwrites = [ - {file = "atomicwrites-1.3.0-py2.py3-none-any.whl", hash = "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4"}, - {file = "atomicwrites-1.3.0.tar.gz", hash = "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"}, + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, ] attrs = [ {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, ] certifi = [ - {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"}, - {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"}, + {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, + {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, ] chardet = [ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] click = [ - {file = "click-7.1.1-py2.py3-none-any.whl", hash = "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"}, - {file = "click-7.1.1.tar.gz", hash = "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc"}, + {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, + {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, ] colorama = [ {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, @@ -507,31 +474,31 @@ dis3 = [ {file = "dis3-0.1.3.tar.gz", hash = "sha256:9259b881fc1df02ed12ac25f82d4a85b44241854330b1a651e40e0c675cb2d1e"}, ] flask = [ - {file = "Flask-1.1.1-py2.py3-none-any.whl", hash = "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6"}, - {file = "Flask-1.1.1.tar.gz", hash = "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52"}, + {file = "Flask-1.1.2-py2.py3-none-any.whl", hash = "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"}, + {file = "Flask-1.1.2.tar.gz", hash = "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060"}, ] flask-httpauth = [ - {file = "Flask-HTTPAuth-3.3.0.tar.gz", hash = "sha256:6ef8b761332e780f9ff74d5f9056c2616f52babc1998b01d9f361a1e439e61b9"}, - {file = "Flask_HTTPAuth-3.3.0-py2.py3-none-any.whl", hash = "sha256:0149953720489407e51ec24bc2f86273597b7973d71cd51f9443bd0e2a89bd72"}, + {file = "Flask-HTTPAuth-4.1.0.tar.gz", hash = "sha256:9e028e4375039a49031eb9ecc40be4761f0540476040f6eff329a31dabd4d000"}, + {file = "Flask_HTTPAuth-4.1.0-py2.py3-none-any.whl", hash = "sha256:29e0288869a213c7387f0323b6bf2c7191584fb1da8aa024d9af118e5cd70de7"}, ] future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, ] idna = [ - {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, - {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, + {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, + {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, ] importlib-metadata = [ - {file = "importlib_metadata-1.5.0-py2.py3-none-any.whl", hash = "sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b"}, - {file = "importlib_metadata-1.5.0.tar.gz", hash = "sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302"}, + {file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"}, + {file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"}, ] itsdangerous = [ {file = "itsdangerous-1.1.0-py2.py3-none-any.whl", hash = "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"}, {file = "itsdangerous-1.1.0.tar.gz", hash = "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19"}, ] jinja2 = [ - {file = "Jinja2-2.11.1-py2.py3-none-any.whl", hash = "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"}, - {file = "Jinja2-2.11.1.tar.gz", hash = "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250"}, + {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"}, + {file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"}, ] macholib = [ {file = "macholib-1.14-py2.py3-none-any.whl", hash = "sha256:c500f02867515e6c60a27875b408920d18332ddf96b4035ef03beddd782d4281"}, @@ -573,15 +540,12 @@ markupsafe = [ {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, ] more-itertools = [ - {file = "more-itertools-8.2.0.tar.gz", hash = "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507"}, - {file = "more_itertools-8.2.0-py3-none-any.whl", hash = "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c"}, + {file = "more-itertools-8.4.0.tar.gz", hash = "sha256:68c70cc7167bdf5c7c9d8f6954a7837089c6a36bf565383919bb595efb8a17e5"}, + {file = "more_itertools-8.4.0-py3-none-any.whl", hash = "sha256:b78134b2063dd214000685165d81c154522c3ee0a1c0d4d113c80361c234c5a2"}, ] packaging = [ - {file = "packaging-20.3-py2.py3-none-any.whl", hash = "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"}, - {file = "packaging-20.3.tar.gz", hash = "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3"}, -] -pathtools = [ - {file = "pathtools-0.1.2.tar.gz", hash = "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0"}, + {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, + {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, ] pefile = [ {file = "pefile-2019.4.18.tar.gz", hash = "sha256:a5d6e8305c6b210849b47a6174ddf9c452b2888340b8177874b862ba6c207645"}, @@ -590,61 +554,48 @@ pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] -psutil = [ - {file = "psutil-5.7.0-cp27-none-win32.whl", hash = "sha256:298af2f14b635c3c7118fd9183843f4e73e681bb6f01e12284d4d70d48a60953"}, - {file = "psutil-5.7.0-cp27-none-win_amd64.whl", hash = "sha256:75e22717d4dbc7ca529ec5063000b2b294fc9a367f9c9ede1f65846c7955fd38"}, - {file = "psutil-5.7.0-cp35-cp35m-win32.whl", hash = "sha256:f344ca230dd8e8d5eee16827596f1c22ec0876127c28e800d7ae20ed44c4b310"}, - {file = "psutil-5.7.0-cp35-cp35m-win_amd64.whl", hash = "sha256:e2d0c5b07c6fe5a87fa27b7855017edb0d52ee73b71e6ee368fae268605cc3f5"}, - {file = "psutil-5.7.0-cp36-cp36m-win32.whl", hash = "sha256:a02f4ac50d4a23253b68233b07e7cdb567bd025b982d5cf0ee78296990c22d9e"}, - {file = "psutil-5.7.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1413f4158eb50e110777c4f15d7c759521703bd6beb58926f1d562da40180058"}, - {file = "psutil-5.7.0-cp37-cp37m-win32.whl", hash = "sha256:d008ddc00c6906ec80040d26dc2d3e3962109e40ad07fd8a12d0284ce5e0e4f8"}, - {file = "psutil-5.7.0-cp37-cp37m-win_amd64.whl", hash = "sha256:73f35ab66c6c7a9ce82ba44b1e9b1050be2a80cd4dcc3352cc108656b115c74f"}, - {file = "psutil-5.7.0-cp38-cp38-win32.whl", hash = "sha256:60b86f327c198561f101a92be1995f9ae0399736b6eced8f24af41ec64fb88d4"}, - {file = "psutil-5.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:d84029b190c8a66a946e28b4d3934d2ca1528ec94764b180f7d6ea57b0e75e26"}, - {file = "psutil-5.7.0.tar.gz", hash = "sha256:685ec16ca14d079455892f25bd124df26ff9137664af445563c1bd36629b5e0e"}, -] py = [ - {file = "py-1.8.1-py2.py3-none-any.whl", hash = "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"}, - {file = "py-1.8.1.tar.gz", hash = "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa"}, + {file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"}, + {file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"}, ] pycryptodome = [ - {file = "pycryptodome-3.9.7-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:0e10f352ccbbcb5bb2dc4ecaf106564e65702a717d72ab260f9ac4c19753cfc2"}, - {file = "pycryptodome-3.9.7-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:9c739b7795ccf2ef1fdad8d44e539a39ad300ee6786e804ea7f0c6a786eb5343"}, - {file = "pycryptodome-3.9.7-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9977086e0f93adb326379897437373871b80501e1d176fec63c7f46fb300c862"}, - {file = "pycryptodome-3.9.7-cp27-cp27m-win32.whl", hash = "sha256:83295a3fb5cf50c48631eb5b440cb5e9832d8c14d81d1d45f4497b67a9987de8"}, - {file = "pycryptodome-3.9.7-cp27-cp27m-win_amd64.whl", hash = "sha256:b1e332587b3b195542e77681389c296e1837ca01240399d88803a075447d3557"}, - {file = "pycryptodome-3.9.7-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:9378c309aec1f8cd8bad361ed0816a440151b97a2a3f6ffdaba1d1a1fb76873a"}, - {file = "pycryptodome-3.9.7-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4f94368ce2d65873a87ad867eb3bf63f4ba81eb97a9ee66d38c2b71ce5a7439"}, - {file = "pycryptodome-3.9.7-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:f655addaaaa9974108d4808f4150652589cada96074c87115c52e575bfcd87d5"}, - {file = "pycryptodome-3.9.7-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:9a94fca11fdc161460bd8659c15b6adef45c1b20da86402256eaf3addfaab324"}, - {file = "pycryptodome-3.9.7-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:ea83bcd9d6c03248ebd46e71ac313858e0afd5aa2fa81478c0e653242f3eb476"}, - {file = "pycryptodome-3.9.7-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:07024fc364869eae8d6ac0d316e089956e6aeffe42dbdcf44fe1320d96becf7f"}, - {file = "pycryptodome-3.9.7-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:426c188c83c10df71f053e04b4003b1437bae5cb37606440e498b00f160d71d0"}, - {file = "pycryptodome-3.9.7-cp35-cp35m-win32.whl", hash = "sha256:d61b012baa8c2b659e9890011358455c0019a4108536b811602d2f638c40802a"}, - {file = "pycryptodome-3.9.7-cp35-cp35m-win_amd64.whl", hash = "sha256:1f4752186298caf2e9ff5354f2e694d607ca7342aa313a62005235d46e28cf04"}, - {file = "pycryptodome-3.9.7-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:767ad0fb5d23efc36a4d5c2fc608ac603f3de028909bcf59abc943e0d0bc5a36"}, - {file = "pycryptodome-3.9.7-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:2fbc472e0b567318fe2052281d5a8c0ae70099b446679815f655e9fbc18c3a65"}, - {file = "pycryptodome-3.9.7-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:9230fcb5d948c3fb40049bace4d33c5d254f8232c2c0bba05d2570aea3ba4520"}, - {file = "pycryptodome-3.9.7-cp36-cp36m-win32.whl", hash = "sha256:8f06556a8f7ea7b1e42eff39726bb0dca1c251205debae64e6eebea3cd7b438a"}, - {file = "pycryptodome-3.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:d6e1bc5c94873bec742afe2dfadce0d20445b18e75c47afc0c115b19e5dd38dd"}, - {file = "pycryptodome-3.9.7-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:3ec3dc2f80f71fd0c955ce48b81bfaf8914c6f63a41a738f28885a1c4892968a"}, - {file = "pycryptodome-3.9.7-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cff31f5a8977534f255f729d5d2467526f2b10563a30bbdade92223e0bf264bd"}, - {file = "pycryptodome-3.9.7-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ed5761b37615a1f222c5345bbf45272ae2cf8c7dff88a4f53a1e9f977cbb6d95"}, - {file = "pycryptodome-3.9.7-cp37-cp37m-win32.whl", hash = "sha256:f011cd0062e54658b7086a76f8cf0f4222812acc66e219e196ea2d0a8849d0ed"}, - {file = "pycryptodome-3.9.7-cp37-cp37m-win_amd64.whl", hash = "sha256:626c0a1d4d83ec6303f970a17158114f75c3ba1736f7f2983f7b40a265861bd8"}, - {file = "pycryptodome-3.9.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be56bde3312e022d9d1d6afa124556460ad5c844c2fc63642f6af723c098d35"}, - {file = "pycryptodome-3.9.7-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c818dc1f3eace93ee50c2b6b5c2becf7c418fa5dd1ba6fc0ef7db279ea21d5e4"}, - {file = "pycryptodome-3.9.7-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:09b6d6bcc01a4eb1a2b4deeff5aa602a108ec5aed8ac75ae554f97d1d7f0a5ad"}, - {file = "pycryptodome-3.9.7-cp38-cp38-win32.whl", hash = "sha256:7ac729d9091ed5478af2b4a4f44f5335a98febbc008af619e4569a59fe503e40"}, - {file = "pycryptodome-3.9.7-cp38-cp38-win_amd64.whl", hash = "sha256:c109a26a21f21f695d369ff9b87f5d43e0d6c768d8384e10bc74142bed2e092e"}, - {file = "pycryptodome-3.9.7.tar.gz", hash = "sha256:f1add21b6d179179b3c177c33d18a2186a09cc0d3af41ff5ed3f377360b869f2"}, + {file = "pycryptodome-3.9.8-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:50348edd283afdccddc0938cdc674484533912ba8a99a27c7bfebb75030aa856"}, + {file = "pycryptodome-3.9.8-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:80d57177a0b7c14d4594c62bbb47fe2f6309ad3b0a34348a291d570925c97a82"}, + {file = "pycryptodome-3.9.8-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:fbe65d5cfe04ff2f7684160d50f5118bdefb01e3af4718eeb618bfed40f19d94"}, + {file = "pycryptodome-3.9.8-cp27-cp27m-win32.whl", hash = "sha256:bcd5b8416e73e4b0d48afba3704d8c826414764dafaed7a1a93c442188d90ccc"}, + {file = "pycryptodome-3.9.8-cp27-cp27m-win_amd64.whl", hash = "sha256:360955eece2cd0fa694a708d10303c6abd7b39614fa2547b6bd245da76198beb"}, + {file = "pycryptodome-3.9.8-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:1e655746f539421d923fd48df8f6f40b3443d80b75532501c0085b64afed9df5"}, + {file = "pycryptodome-3.9.8-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:709b9f144d23e290b9863121d1ace14a72e01f66ea9c903fbdc690520dfdfcf0"}, + {file = "pycryptodome-3.9.8-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:6276478ada411aca97c0d5104916354b3d740d368407912722bd4d11aa9ee4c2"}, + {file = "pycryptodome-3.9.8-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:54bdedd28476dea8a3cd86cb67c0df1f0e3d71cae8022354b0f879c41a3d27b2"}, + {file = "pycryptodome-3.9.8-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f521178e5a991ffd04182ed08f552daca1affcb826aeda0e1945cd989a9d4345"}, + {file = "pycryptodome-3.9.8-cp35-cp35m-win32.whl", hash = "sha256:a207231a52426de3ff20f5608f0687261a3329d97a036c51f7d4c606a6f30c23"}, + {file = "pycryptodome-3.9.8-cp35-cp35m-win_amd64.whl", hash = "sha256:2b998dc45ef5f4e5cf5248a6edfcd8d8e9fb5e35df8e4259b13a1b10eda7b16b"}, + {file = "pycryptodome-3.9.8-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:03d5cca8618620f45fd40f827423f82b86b3a202c8d44108601b0f5f56b04299"}, + {file = "pycryptodome-3.9.8-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:f78a68c2c820e4731e510a2df3eef0322f24fde1781ced970bf497b6c7d92982"}, + {file = "pycryptodome-3.9.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:132a56abba24e2e06a479d8e5db7a48271a73a215f605017bbd476d31f8e71c1"}, + {file = "pycryptodome-3.9.8-cp36-cp36m-win32.whl", hash = "sha256:67dcad1b8b201308586a8ca2ffe89df1e4f731d5a4cdd0610cc4ea790351c739"}, + {file = "pycryptodome-3.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:b56638d58a3a4be13229c6a815cd448f9e3ce40c00880a5398471b42ee86f50e"}, + {file = "pycryptodome-3.9.8-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:bec2bcdf7c9ce7f04d718e51887f3b05dc5c1cfaf5d2c2e9065ecddd1b2f6c9a"}, + {file = "pycryptodome-3.9.8-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:abc2e126c9490e58a36a0f83516479e781d83adfb134576a5cbe5c6af2a3e93c"}, + {file = "pycryptodome-3.9.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ef39c98d9b8c0736d91937d193653e47c3b19ddf4fc3bccdc5e09aaa4b0c5d21"}, + {file = "pycryptodome-3.9.8-cp37-cp37m-win32.whl", hash = "sha256:4350a42028240c344ee855f032c7d4ad6ff4f813bfbe7121547b7dc579ecc876"}, + {file = "pycryptodome-3.9.8-cp37-cp37m-win_amd64.whl", hash = "sha256:c8bf40cf6e281a4378e25846924327e728a887e8bf0ee83b2604a0f4b61692e8"}, + {file = "pycryptodome-3.9.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d8074c8448cfd0705dfa71ca333277fce9786d0b9cac75d120545de6253f996a"}, + {file = "pycryptodome-3.9.8-cp38-cp38-manylinux1_i686.whl", hash = "sha256:8063a712fba642f78d3c506b0896846601b6de7f5c3d534e388ad0cc07f5a149"}, + {file = "pycryptodome-3.9.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:dd302b6ae3965afeb5ef1b0d92486f986c0e65183cd7835973f0b593800590e6"}, + {file = "pycryptodome-3.9.8-cp38-cp38-win32.whl", hash = "sha256:02e51e1d5828d58f154896ddfd003e2e7584869c275e5acbe290443575370fba"}, + {file = "pycryptodome-3.9.8-cp38-cp38-win_amd64.whl", hash = "sha256:55eb61aca2c883db770999f50d091ff7c14016f2769ad7bca3d9b75d1d7c1b68"}, + {file = "pycryptodome-3.9.8-cp39-cp39-manylinux1_i686.whl", hash = "sha256:39ef9fb52d6ec7728fce1f1693cb99d60ce302aeebd59bcedea70ca3203fda60"}, + {file = "pycryptodome-3.9.8-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:de6e1cd75677423ff64712c337521e62e3a7a4fc84caabbd93207752e831a85a"}, + {file = "pycryptodome-3.9.8.tar.gz", hash = "sha256:0e24171cf01021bc5dc17d6a9d4f33a048f09d62cc3f62541e95ef104588bda4"}, ] pyinstaller = [ {file = "PyInstaller-3.6.tar.gz", hash = "sha256:3730fa80d088f8bb7084d32480eb87cbb4ddb64123363763cf8f2a1378c1c4b7"}, ] pyparsing = [ - {file = "pyparsing-2.4.6-py2.py3-none-any.whl", hash = "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"}, - {file = "pyparsing-2.4.6.tar.gz", hash = "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f"}, + {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, + {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pyqt5 = [ {file = "PyQt5-5.14.0-5.14.0-cp35.cp36.cp37.cp38-abi3-macosx_10_6_intel.whl", hash = "sha256:895d4101f7f8c82bc728d7eb9da1c756955ce27a0c945eafe7f234dd03402853"}, @@ -654,23 +605,23 @@ pyqt5 = [ {file = "PyQt5-5.14.0.tar.gz", hash = "sha256:0145a6b7de15756366decb736c349a0cb510d706c83fda5b8cd9e0557bc1da72"}, ] pyqt5-sip = [ - {file = "PyQt5_sip-12.7.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:f314f31f5fd39b06897f013f425137e511d45967150eb4e424a363d8138521c6"}, - {file = "PyQt5_sip-12.7.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b42021229424aa44e99b3b49520b799fd64ff6ae8b53f79f903bbd85719a28e4"}, - {file = "PyQt5_sip-12.7.1-cp35-cp35m-win32.whl", hash = "sha256:6b4860c4305980db509415d0af802f111d15f92016c9422eb753bc8883463456"}, - {file = "PyQt5_sip-12.7.1-cp35-cp35m-win_amd64.whl", hash = "sha256:d46b0f8effc554de52a1466b1bd80e5cb4bce635a75ac4e7ad6247c965dec5b9"}, - {file = "PyQt5_sip-12.7.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:3f665376d9e52faa9855c3736a66ce6d825f85c86d7774d3c393f09da23f4f86"}, - {file = "PyQt5_sip-12.7.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1115728644bbadcde5fc8a16e7918bd31915a42dd6fb36b10d4afb78c582753e"}, - {file = "PyQt5_sip-12.7.1-cp36-cp36m-win32.whl", hash = "sha256:cbeeae6b45234a1654657f79943f8bccd3d14b4e7496746c62cf6fbce69442c7"}, - {file = "PyQt5_sip-12.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8da842d3d7bf8931d1093105fb92702276b6dbb7e801abbaaa869405d616171a"}, - {file = "PyQt5_sip-12.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1f4289276d355b6521dc2cc956189315da6f13adfb6bbab8f25ebd15e3bce1d4"}, - {file = "PyQt5_sip-12.7.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c1e730a9eb2ec3869ed5d81b0f99f6e2460fb4d77750444c0ec183b771d798f7"}, - {file = "PyQt5_sip-12.7.1-cp37-cp37m-win32.whl", hash = "sha256:b5b4906445fe980aee76f20400116b6904bf5f30d0767489c13370e42a764020"}, - {file = "PyQt5_sip-12.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7ffa39763097f64de129cf5cc770a651c3f65d2466b4fe05bef2bd2efbaa38e6"}, - {file = "PyQt5_sip-12.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:288c6dc18a8d6a20981c07b715b5695d9b66880778565f3792bc6e38f14f20fb"}, - {file = "PyQt5_sip-12.7.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ee1a12f09d5af2304273bfd2f6b43835c1467d5ed501a6c95f5405637fa7750a"}, - {file = "PyQt5_sip-12.7.1-cp38-cp38-win32.whl", hash = "sha256:8a18e6f45d482ddfe381789979d09ee13aa6450caa3a0476503891bccb3ac709"}, - {file = "PyQt5_sip-12.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:e28c3abc9b62a1b7e796891648b9f14f8167b31c8e7990fae79654777252bb4d"}, - {file = "PyQt5_sip-12.7.1.tar.gz", hash = "sha256:e6078f5ee7d31c102910d0c277a110e1c2a20a3fc88cd017a39e170120586d3f"}, + {file = "PyQt5_sip-12.8.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:9ef12754021bcc1246f97e00ea62b5594dd5c61192830639ab4a1640bd4b7940"}, + {file = "PyQt5_sip-12.8.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:fa3d70f370604efc67085849d3d1d3d2109faa716c520faf601d15845df64de6"}, + {file = "PyQt5_sip-12.8.0-cp35-cp35m-win32.whl", hash = "sha256:61aa60fb848d740581646603a12c2dcb8d7c4cbd2a9c476a1c891ec360ff0b87"}, + {file = "PyQt5_sip-12.8.0-cp35-cp35m-win_amd64.whl", hash = "sha256:8d9f4dc7dbae9783c5dafd66801875a2ebf9302c3addd5739f772285c1c1e91c"}, + {file = "PyQt5_sip-12.8.0-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:9b69db29571dde679908fb237784a8e7af4a2cbf1b7bb25bdb86e487210e04d2"}, + {file = "PyQt5_sip-12.8.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:58eae636e0b1926cddec98a703319a47f671cef07d73aaa525ba421cd4adfeb5"}, + {file = "PyQt5_sip-12.8.0-cp36-cp36m-win32.whl", hash = "sha256:e6254647fa35e1260282aeb9c32a3dd363287b9a1ffcc4f22bd27e54178e92e4"}, + {file = "PyQt5_sip-12.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f4c294bfaf2be8004583266d4621bfd3a387e12946f548f966a7fbec91845f1b"}, + {file = "PyQt5_sip-12.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:224e2fbb7088595940c348d168a317caa2110cbb7a5b957a8c3fc0d9296ee069"}, + {file = "PyQt5_sip-12.8.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5c19c4ad67af087e8f4411da7422391b236b941f5f0697f615c5816455d1355d"}, + {file = "PyQt5_sip-12.8.0-cp37-cp37m-win32.whl", hash = "sha256:2a1153cda63f2632d3d5698f0cf29f6b1f1d5162305dc6f5b23336ad8f1039ed"}, + {file = "PyQt5_sip-12.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:94c80677b1e8c92fa080e24045d54ace5e4343c4ee6d0216675cd91d6f8e122a"}, + {file = "PyQt5_sip-12.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2a2239d16a49ce6eaf10166a84424543111f8ebe49d3c124d02af91b01a58425"}, + {file = "PyQt5_sip-12.8.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b1bbe763d431d26f9565cba3e99866768761366ab6d609d2506d194882156fa7"}, + {file = "PyQt5_sip-12.8.0-cp38-cp38-win32.whl", hash = "sha256:d7b8a8f89385ad9e3da38e0123c22c0efc18005e0e2731b6b95e4c21db2049d2"}, + {file = "PyQt5_sip-12.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:1d65ce08a56282fb0273dd06585b8927b88d4fba71c01a54f8e2ac87ac1ed387"}, + {file = "PyQt5_sip-12.8.0.tar.gz", hash = "sha256:0a34b6596bdd28d52da3a51fa8d9bb0b287bcb605c2512aa3251b9028cc71f4d"}, ] pysocks = [ {file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"}, @@ -678,8 +629,8 @@ pysocks = [ {file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"}, ] pytest = [ - {file = "pytest-5.4.1-py3-none-any.whl", hash = "sha256:0e5b30f5cb04e887b91b1ee519fa3d89049595f428c1db76e73bd7f17b09b172"}, - {file = "pytest-5.4.1.tar.gz", hash = "sha256:84dde37075b8805f3d1f392cc47e38a0e59518fb46a431cfdaf7cf1ce805f970"}, + {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, + {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, ] pytest-faulthandler = [ {file = "pytest-faulthandler-2.0.1.tar.gz", hash = "sha256:ed72bbce87ac344da81eb7d882196a457d4a1026a3da4a57154dacd85cd71ae5"}, @@ -694,30 +645,27 @@ qrcode = [ {file = "qrcode-6.1.tar.gz", hash = "sha256:505253854f607f2abf4d16092c61d4e9d511a3b4392e60bff957a68592b04369"}, ] requests = [ - {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, - {file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"}, + {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, + {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, ] six = [ - {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, - {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, + {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, + {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] stem = [ {file = "stem-1.8.0.tar.gz", hash = "sha256:a0b48ea6224e95f22aa34c0bc3415f0eb4667ddeae3dfb5e32a6920c185568c2"}, ] urllib3 = [ - {file = "urllib3-1.25.8-py2.py3-none-any.whl", hash = "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc"}, - {file = "urllib3-1.25.8.tar.gz", hash = "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"}, -] -watchdog = [ - {file = "watchdog-0.10.2.tar.gz", hash = "sha256:c560efb643faed5ef28784b2245cf8874f939569717a4a12826a173ac644456b"}, + {file = "urllib3-1.25.9-py2.py3-none-any.whl", hash = "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"}, + {file = "urllib3-1.25.9.tar.gz", hash = "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527"}, ] wcwidth = [ - {file = "wcwidth-0.1.8-py2.py3-none-any.whl", hash = "sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603"}, - {file = "wcwidth-0.1.8.tar.gz", hash = "sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8"}, + {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, + {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, ] werkzeug = [ - {file = "Werkzeug-1.0.0-py2.py3-none-any.whl", hash = "sha256:6dc65cf9091cf750012f56f2cad759fa9e879f511b5ff8685e456b4e3bf90d16"}, - {file = "Werkzeug-1.0.0.tar.gz", hash = "sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096"}, + {file = "Werkzeug-1.0.1-py2.py3-none-any.whl", hash = "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43"}, + {file = "Werkzeug-1.0.1.tar.gz", hash = "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c"}, ] zipp = [ {file = "zipp-3.1.0-py3-none-any.whl", hash = "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b"}, diff --git a/pyproject.toml b/pyproject.toml index 411d03f1..029297c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,8 +28,6 @@ requests = "*" stem = "*" urllib3 = "*" Werkzeug = "*" -watchdog = "*" -psutil = "*" qrcode = "^6.1" [tool.poetry.dev-dependencies] @@ -43,8 +41,8 @@ pytest-faulthandler = "*" pytest-qt = "*" six = "*" urllib3 = "*" +setuptools = "*" pyinstaller = {version = "*", platform = "darwin"} -setuptools = {version = "*", platform = "windows"} [build-system] requires = ["poetry>=0.12"] diff --git a/setup.py b/setup.py index e6953370..3e627eb2 100644 --- a/setup.py +++ b/setup.py @@ -70,7 +70,7 @@ classifiers = [ ] data_files = [ ("share/applications", ["install/org.onionshare.OnionShare.desktop"],), - ("share/icons/hicolor/scalable/apps", ["install/org.onionshare.OnionShare.svg"],), + ("share/icons/hicolor/512x512/apps", ["install/org.onionshare.OnionShare.png"],), ("share/metainfo", ["install/org.onionshare.OnionShare.appdata.xml"],), ("share/onionshare", file_list("share")), ("share/onionshare/images", file_list("share/images")), diff --git a/share/locale/en.json b/share/locale/en.json index fa81e4b5..4e67555e 100644 --- a/share/locale/en.json +++ b/share/locale/en.json @@ -22,6 +22,7 @@ "gui_receive_start_server": "Start Receive Mode", "gui_receive_stop_server": "Stop Receive Mode", "gui_receive_stop_server_autostop_timer": "Stop Receive Mode ({} remaining)", + "gui_receive_flatpak_data_dir": "Because you installed OnionShare using flatpak, you must save files to a folder in ~/OnionShare.", "gui_copy_url": "Copy Address", "gui_copy_hidservauth": "Copy HidServAuth", "gui_canceled": "Canceled", @@ -145,7 +146,7 @@ "gui_settings_data_dir_label": "Save files to", "gui_settings_data_dir_browse_button": "Browse", "gui_settings_public_mode_checkbox": "Public mode", - "gui_open_folder_error_nautilus": "Cannot open folder because nautilus is not available. The file is here: {}", + "gui_open_folder_error": "Failed to open folder with xdg-open. The file is here: {}", "gui_settings_language_label": "Preferred language", "gui_settings_language_changed_notice": "Restart OnionShare for the new language to be applied.", "systray_menu_exit": "Quit", @@ -209,4 +210,4 @@ "mode_settings_receive_data_dir_label": "Save files to", "mode_settings_receive_data_dir_browse_button": "Browse", "mode_settings_website_disable_csp_checkbox": "Disable Content Security Policy header (allows your website to use third-party resources)" -} +} \ No newline at end of file diff --git a/tests/test_cli_common.py b/tests/test_cli_common.py index 1f230295..3592d1ba 100644 --- a/tests/test_cli_common.py +++ b/tests/test_cli_common.py @@ -227,12 +227,16 @@ class TestGetTorPaths: # @pytest.mark.skipif(sys.platform != 'Linux', reason='requires Linux') ? def test_get_tor_paths_linux(self, platform_linux, common_obj): - assert common_obj.get_tor_paths() == ( - "/usr/bin/tor", - "/usr/share/tor/geoip", - "/usr/share/tor/geoip6", - "/usr/bin/obfs4proxy", - ) + ( + tor_path, + tor_geo_ip_file_path, + tor_geo_ipv6_file_path, + _, # obfs4proxy is optional + ) = common_obj.get_tor_paths() + + assert os.path.basename(tor_path) == "tor" + assert tor_geo_ip_file_path == "/usr/share/tor/geoip" + assert tor_geo_ipv6_file_path == "/usr/share/tor/geoip6" # @pytest.mark.skipif(sys.platform != 'Windows', reason='requires Windows') ? def test_get_tor_paths_windows(self, platform_windows, common_obj, sys_frozen):