mirror of
https://github.com/onionshare/onionshare.git
synced 2025-09-23 05:54:44 -04:00
Merge develop and resolve conflict
This commit is contained in:
commit
dd7938a134
157 changed files with 3527 additions and 2252 deletions
|
@ -38,14 +38,6 @@ from .onionshare import OnionShare
|
|||
from .mode_settings import ModeSettings
|
||||
|
||||
|
||||
def build_url(mode_settings, app, web):
|
||||
# Build the URL
|
||||
if mode_settings.get("general", "public"):
|
||||
return f"http://{app.onion_host}"
|
||||
else:
|
||||
return f"http://onionshare:{web.password}@{app.onion_host}"
|
||||
|
||||
|
||||
def main(cwd=None):
|
||||
"""
|
||||
The main() function implements all of the logic that the command-line version of
|
||||
|
@ -113,7 +105,7 @@ def main(cwd=None):
|
|||
action="store_true",
|
||||
dest="public",
|
||||
default=False,
|
||||
help="Don't use a password",
|
||||
help="Don't use a private key",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--auto-start-timer",
|
||||
|
@ -129,20 +121,6 @@ def main(cwd=None):
|
|||
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(
|
||||
"--no-autostop-sharing",
|
||||
|
@ -215,8 +193,6 @@ def main(cwd=None):
|
|||
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 = not bool(args.no_autostop_sharing)
|
||||
data_dir = args.data_dir
|
||||
webhook_url = args.webhook_url
|
||||
|
@ -237,13 +213,6 @@ def main(cwd=None):
|
|||
# Verbose mode?
|
||||
common.verbose = verbose
|
||||
|
||||
# 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
|
||||
if config_filename:
|
||||
common.load_settings(config_filename)
|
||||
|
@ -264,8 +233,6 @@ def main(cwd=None):
|
|||
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":
|
||||
|
@ -352,11 +319,6 @@ def main(cwd=None):
|
|||
try:
|
||||
common.settings.load()
|
||||
|
||||
if mode_settings.get("general", "public"):
|
||||
web.password = None
|
||||
else:
|
||||
web.generate_password(mode_settings.get("onion", "password"))
|
||||
|
||||
# Receive mode needs to know the tor proxy details for webhooks
|
||||
if mode == "receive":
|
||||
if local_only:
|
||||
|
@ -381,7 +343,7 @@ def main(cwd=None):
|
|||
sys.exit()
|
||||
|
||||
app.start_onion_service(mode, mode_settings, False)
|
||||
url = build_url(mode_settings, app, web)
|
||||
url = f"http://{app.onion_host}"
|
||||
schedule = datetime.now() + timedelta(seconds=autostart_timer)
|
||||
if mode == "receive":
|
||||
print(
|
||||
|
@ -394,21 +356,21 @@ def main(cwd=None):
|
|||
"what you are doing."
|
||||
)
|
||||
print("")
|
||||
if mode_settings.get("general", "client_auth"):
|
||||
if not mode_settings.get("general", "public"):
|
||||
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 private key to your sender, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}"
|
||||
)
|
||||
print(app.auth_string)
|
||||
print(f"Private key: {app.auth_string}")
|
||||
else:
|
||||
print(
|
||||
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:
|
||||
if mode_settings.get("general", "client_auth"):
|
||||
if not mode_settings.get("general", "public"):
|
||||
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 private key to your recipient, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}"
|
||||
)
|
||||
print(app.auth_string)
|
||||
print(f"Private key: {app.auth_string}")
|
||||
else:
|
||||
print(
|
||||
f"Give this address to your recipient, and tell them it won't be accessible until: {schedule.strftime('%I:%M:%S%p, %b %d, %y')}"
|
||||
|
@ -426,7 +388,6 @@ def main(cwd=None):
|
|||
sys.exit()
|
||||
except (TorTooOldEphemeral, TorTooOldStealth, TorErrorProtocolError) as e:
|
||||
print("")
|
||||
print(e.args[0])
|
||||
sys.exit()
|
||||
|
||||
if mode == "website":
|
||||
|
@ -458,21 +419,14 @@ def main(cwd=None):
|
|||
t.start()
|
||||
|
||||
try: # Trap Ctrl-C
|
||||
# Wait for web.generate_password() to finish running
|
||||
time.sleep(0.2)
|
||||
|
||||
# start auto-stop timer thread
|
||||
if app.autostop_timer > 0:
|
||||
app.autostop_timer_thread.start()
|
||||
|
||||
# Save the web password if we are using a persistent private key
|
||||
if mode_settings.get("persistent", "enabled"):
|
||||
if not mode_settings.get("onion", "password"):
|
||||
mode_settings.set("onion", "password", web.password)
|
||||
# mode_settings.save()
|
||||
|
||||
# Build the URL
|
||||
url = build_url(mode_settings, app, web)
|
||||
url = f"http://{app.onion_host}"
|
||||
|
||||
print("")
|
||||
if autostart_timer > 0:
|
||||
|
@ -490,21 +444,21 @@ def main(cwd=None):
|
|||
)
|
||||
print("")
|
||||
|
||||
if mode_settings.get("general", "client_auth"):
|
||||
print("Give this address and HidServAuth to the sender:")
|
||||
print(url)
|
||||
print(app.auth_string)
|
||||
else:
|
||||
if mode_settings.get("general", "public"):
|
||||
print("Give this address to the sender:")
|
||||
print(url)
|
||||
else:
|
||||
if mode_settings.get("general", "client_auth"):
|
||||
print("Give this address and HidServAuth line to the recipient:")
|
||||
print(url)
|
||||
print(app.auth_string)
|
||||
else:
|
||||
print("Give this address and private key to the sender:")
|
||||
print(url)
|
||||
print(f"Private key: {app.auth_string}")
|
||||
else:
|
||||
if mode_settings.get("general", "public"):
|
||||
print("Give this address to the recipient:")
|
||||
print(url)
|
||||
else:
|
||||
print("Give this address and private key to the recipient:")
|
||||
print(url)
|
||||
print(f"Private key: {app.auth_string}")
|
||||
print("")
|
||||
print("Press Ctrl+C to stop the server")
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@ class ModeSettings:
|
|||
self.default_settings = {
|
||||
"onion": {
|
||||
"private_key": None,
|
||||
"hidservauth_string": None,
|
||||
"password": None,
|
||||
"client_auth_priv_key": None,
|
||||
"client_auth_pub_key": None,
|
||||
},
|
||||
"persistent": {"mode": None, "enabled": False},
|
||||
"general": {
|
||||
|
@ -46,8 +46,6 @@ class ModeSettings:
|
|||
"public": False,
|
||||
"autostart_timer": False,
|
||||
"autostop_timer": False,
|
||||
"legacy": False,
|
||||
"client_auth": False,
|
||||
"service_id": None,
|
||||
},
|
||||
"share": {"autostop_sharing": True, "filenames": []},
|
||||
|
|
|
@ -21,8 +21,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
from stem.control import Controller
|
||||
from stem import ProtocolError, SocketClosed
|
||||
from stem.connection import MissingPassword, UnreadableCookieFile, AuthenticationFailure
|
||||
from Crypto.PublicKey import RSA
|
||||
import base64
|
||||
import nacl.public
|
||||
import os
|
||||
import tempfile
|
||||
import subprocess
|
||||
|
@ -170,6 +170,20 @@ class Onion(object):
|
|||
# Keep track of onions where it's important to gracefully close to prevent truncated downloads
|
||||
self.graceful_close_onions = []
|
||||
|
||||
def key_str(self, key):
|
||||
"""
|
||||
Returns a base32 decoded string of a key.
|
||||
"""
|
||||
# bytes to base 32
|
||||
key_bytes = bytes(key)
|
||||
key_b32 = base64.b32encode(key_bytes)
|
||||
# strip trailing ====
|
||||
assert key_b32[-4:] == b'===='
|
||||
key_b32 = key_b32[:-4]
|
||||
# change from b'ASDF' to ASDF
|
||||
s = key_b32.decode('utf-8')
|
||||
return s
|
||||
|
||||
def connect(
|
||||
self,
|
||||
custom_settings=None,
|
||||
|
@ -570,14 +584,15 @@ class Onion(object):
|
|||
callable(list_ephemeral_hidden_services) and self.tor_version >= "0.2.7.1"
|
||||
)
|
||||
|
||||
# Do the versions of stem and tor that I'm using support stealth onion services?
|
||||
# Do the versions of stem and tor that I'm using support v3 stealth onion services?
|
||||
try:
|
||||
res = self.c.create_ephemeral_hidden_service(
|
||||
{1: 1},
|
||||
basic_auth={"onionshare": None},
|
||||
basic_auth=None,
|
||||
await_publication=False,
|
||||
key_type="NEW",
|
||||
key_content="RSA1024",
|
||||
key_content="ED25519-V3",
|
||||
client_auth_v3="E2GOT5LTUTP3OAMRCRXO4GSH6VKJEUOXZQUC336SRKAHTTT5OVSA",
|
||||
)
|
||||
tmp_service_id = res.service_id
|
||||
self.c.remove_ephemeral_hidden_service(tmp_service_id)
|
||||
|
@ -612,65 +627,58 @@ class Onion(object):
|
|||
"Your version of Tor is too old, ephemeral onion services are not supported"
|
||||
)
|
||||
raise TorTooOldEphemeral()
|
||||
if mode_settings.get("general", "client_auth") and not self.supports_stealth:
|
||||
print(
|
||||
"Your version of Tor is too old, stealth onion services are not supported"
|
||||
)
|
||||
raise TorTooOldStealth()
|
||||
|
||||
auth_cookie = None
|
||||
if mode_settings.get("general", "client_auth"):
|
||||
if mode_settings.get("onion", "hidservauth_string"):
|
||||
auth_cookie = mode_settings.get("onion", "hidservauth_string").split()[
|
||||
2
|
||||
]
|
||||
if auth_cookie:
|
||||
basic_auth = {"onionshare": auth_cookie}
|
||||
else:
|
||||
# If we had neither a scheduled auth cookie or a persistent hidservauth string,
|
||||
# set the cookie to 'None', which means Tor will create one for us
|
||||
basic_auth = {"onionshare": None}
|
||||
else:
|
||||
# Not using client auth at all
|
||||
basic_auth = None
|
||||
|
||||
if mode_settings.get("onion", "private_key"):
|
||||
key_content = mode_settings.get("onion", "private_key")
|
||||
if self.is_v2_key(key_content):
|
||||
key_type = "RSA1024"
|
||||
else:
|
||||
# Assume it was a v3 key. Stem will throw an error if it's something illegible
|
||||
key_type = "ED25519-V3"
|
||||
key_type = "ED25519-V3"
|
||||
else:
|
||||
key_content = "ED25519-V3"
|
||||
key_type = "NEW"
|
||||
# Work out if we can support v3 onion services, which are preferred
|
||||
if self.supports_v3_onions and not mode_settings.get("general", "legacy"):
|
||||
key_content = "ED25519-V3"
|
||||
else:
|
||||
# fall back to v2 onion services
|
||||
key_content = "RSA1024"
|
||||
|
||||
# v3 onions don't yet support basic auth. Our ticket:
|
||||
# https://github.com/micahflee/onionshare/issues/697
|
||||
if (
|
||||
key_type == "NEW"
|
||||
and key_content == "ED25519-V3"
|
||||
and not mode_settings.get("general", "legacy")
|
||||
):
|
||||
basic_auth = None
|
||||
|
||||
debug_message = f"key_type={key_type}"
|
||||
if key_type == "NEW":
|
||||
debug_message += f", key_content={key_content}"
|
||||
self.common.log("Onion", "start_onion_service", debug_message)
|
||||
|
||||
if mode_settings.get("general", "public"):
|
||||
client_auth_priv_key = None
|
||||
client_auth_pub_key = None
|
||||
else:
|
||||
if not self.supports_stealth:
|
||||
print(
|
||||
"Your version of Tor is too old, stealth onion services are not supported"
|
||||
)
|
||||
raise TorTooOldStealth()
|
||||
else:
|
||||
if key_type == "NEW" or not mode_settings.get("onion", "client_auth_priv_key"):
|
||||
# Generate a new key pair for Client Auth on new onions, or if
|
||||
# it's a persistent onion but for some reason we don't them
|
||||
client_auth_priv_key_raw = nacl.public.PrivateKey.generate()
|
||||
client_auth_priv_key = self.key_str(client_auth_priv_key_raw)
|
||||
client_auth_pub_key = self.key_str(client_auth_priv_key_raw.public_key)
|
||||
else:
|
||||
# These should have been saved in settings from the previous run of a persistent onion
|
||||
client_auth_priv_key = mode_settings.get("onion", "client_auth_priv_key")
|
||||
client_auth_pub_key = mode_settings.get("onion", "client_auth_pub_key")
|
||||
|
||||
try:
|
||||
res = self.c.create_ephemeral_hidden_service(
|
||||
{80: port},
|
||||
await_publication=await_publication,
|
||||
basic_auth=basic_auth,
|
||||
key_type=key_type,
|
||||
key_content=key_content,
|
||||
)
|
||||
if not self.supports_stealth:
|
||||
res = self.c.create_ephemeral_hidden_service(
|
||||
{80: port},
|
||||
await_publication=await_publication,
|
||||
basic_auth=None,
|
||||
key_type=key_type,
|
||||
key_content=key_content,
|
||||
)
|
||||
else:
|
||||
res = self.c.create_ephemeral_hidden_service(
|
||||
{80: port},
|
||||
await_publication=await_publication,
|
||||
basic_auth=None,
|
||||
key_type=key_type,
|
||||
key_content=key_content,
|
||||
client_auth_v3=client_auth_pub_key,
|
||||
)
|
||||
|
||||
except ProtocolError as e:
|
||||
print("Tor error: {}".format(e.args[0]))
|
||||
|
@ -688,12 +696,20 @@ class Onion(object):
|
|||
# Save the private key and hidservauth string
|
||||
if not mode_settings.get("onion", "private_key"):
|
||||
mode_settings.set("onion", "private_key", res.private_key)
|
||||
if mode_settings.get("general", "client_auth") and not mode_settings.get(
|
||||
"onion", "hidservauth_string"
|
||||
):
|
||||
auth_cookie = list(res.client_auth.values())[0]
|
||||
self.auth_string = f"HidServAuth {onion_host} {auth_cookie}"
|
||||
mode_settings.set("onion", "hidservauth_string", self.auth_string)
|
||||
|
||||
# If using V3 onions and Client Auth, save both the private and public key
|
||||
# because we need to send the public key to ADD_ONION (if we restart this
|
||||
# same share at a later date), and the private key to the other user for
|
||||
# their Tor Browser.
|
||||
if not mode_settings.get("general", "public"):
|
||||
mode_settings.set("onion", "client_auth_priv_key", client_auth_priv_key)
|
||||
mode_settings.set("onion", "client_auth_pub_key", client_auth_pub_key)
|
||||
# If we were pasting the client auth directly into the filesystem behind a Tor client,
|
||||
# it would need to be in the format below. However, let's just set the private key
|
||||
# by itself, as this can be pasted directly into Tor Browser, which is likely to
|
||||
# be the most common use case.
|
||||
# self.auth_string = f"{onion_host}:x25519:{client_auth_priv_key}"
|
||||
self.auth_string = client_auth_priv_key
|
||||
|
||||
return onion_host
|
||||
|
||||
|
@ -825,15 +841,3 @@ class Onion(object):
|
|||
return ("127.0.0.1", 9150)
|
||||
else:
|
||||
return (self.settings.get("socks_address"), self.settings.get("socks_port"))
|
||||
|
||||
def is_v2_key(self, key):
|
||||
"""
|
||||
Helper function for determining if a key is RSA1024 (v2) or not.
|
||||
"""
|
||||
try:
|
||||
# Import the key
|
||||
key = RSA.importKey(base64.b64decode(key))
|
||||
# Is this a v2 Onion key? (1024 bits) If so, we should keep using it.
|
||||
return key.n.bit_length() == 1024
|
||||
except Exception:
|
||||
return False
|
||||
|
|
|
@ -74,13 +74,15 @@ class OnionShare(object):
|
|||
|
||||
if self.local_only:
|
||||
self.onion_host = f"127.0.0.1:{self.port}"
|
||||
if not mode_settings.get("general", "public"):
|
||||
self.auth_string = "E2GOT5LTUTP3OAMRCRXO4GSH6VKJEUOXZQUC336SRKAHTTT5OVSA"
|
||||
return
|
||||
|
||||
self.onion_host = self.onion.start_onion_service(
|
||||
mode, mode_settings, self.port, await_publication
|
||||
)
|
||||
|
||||
if mode_settings.get("general", "client_auth"):
|
||||
if not mode_settings.get("general", "public"):
|
||||
self.auth_string = self.onion.auth_string
|
||||
|
||||
def stop_onion_service(self, mode_settings):
|
||||
|
|
|
@ -229,6 +229,7 @@ ul.breadcrumbs li a:link, ul.breadcrumbs li a:visited {
|
|||
display: block;
|
||||
}
|
||||
.chat-wrapper .message {
|
||||
word-break: break-word;
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
margin-bottom: 0.3em;
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>OnionShare: 401 Unauthorized Access</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="{{ static_url_path }}/img/favicon.ico" rel="icon" type="image/x-icon" />
|
||||
<link rel="stylesheet" rel="subresource" type="text/css" href="{{ static_url_path }}/css/style.css" media="all">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="info-wrapper">
|
||||
<div class="info">
|
||||
<p><img class="logo" src="{{ static_url_path }}/img/logo_large.png" title="OnionShare"></p>
|
||||
<p class="info-header">401 Unauthorized Access</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1 +1 @@
|
|||
2.3.2.dev1
|
||||
2.3.3
|
|
@ -75,6 +75,7 @@ class Settings(object):
|
|||
"it": "Italiano", # Italian
|
||||
"ja": "日本語", # Japanese
|
||||
"ckb": "Soranî", # Kurdish (Central)
|
||||
"lt": "Lietuvių Kalba", # Lithuanian
|
||||
"nb_NO": "Norsk Bokmål", # Norwegian Bokmål
|
||||
# "fa": "فارسی", # Persian
|
||||
"pl": "Polski", # Polish
|
||||
|
@ -110,6 +111,7 @@ class Settings(object):
|
|||
"tor_bridges_use_custom_bridges": "",
|
||||
"persistent_tabs": [],
|
||||
"locale": None, # this gets defined in fill_in_defaults()
|
||||
"theme": 0,
|
||||
}
|
||||
self._settings = {}
|
||||
self.fill_in_defaults()
|
||||
|
|
|
@ -34,7 +34,6 @@ from flask import (
|
|||
send_file,
|
||||
__version__ as flask_version,
|
||||
)
|
||||
from flask_httpauth import HTTPBasicAuth
|
||||
from flask_socketio import SocketIO
|
||||
|
||||
from .share_mode import ShareModeWeb
|
||||
|
@ -64,18 +63,16 @@ class Web:
|
|||
REQUEST_STARTED = 1
|
||||
REQUEST_PROGRESS = 2
|
||||
REQUEST_CANCELED = 3
|
||||
REQUEST_RATE_LIMIT = 4
|
||||
REQUEST_UPLOAD_INCLUDES_MESSAGE = 5
|
||||
REQUEST_UPLOAD_FILE_RENAMED = 6
|
||||
REQUEST_UPLOAD_SET_DIR = 7
|
||||
REQUEST_UPLOAD_FINISHED = 8
|
||||
REQUEST_UPLOAD_CANCELED = 9
|
||||
REQUEST_INDIVIDUAL_FILE_STARTED = 10
|
||||
REQUEST_INDIVIDUAL_FILE_PROGRESS = 11
|
||||
REQUEST_INDIVIDUAL_FILE_CANCELED = 12
|
||||
REQUEST_ERROR_DATA_DIR_CANNOT_CREATE = 13
|
||||
REQUEST_OTHER = 14
|
||||
REQUEST_INVALID_PASSWORD = 15
|
||||
REQUEST_UPLOAD_INCLUDES_MESSAGE = 4
|
||||
REQUEST_UPLOAD_FILE_RENAMED = 5
|
||||
REQUEST_UPLOAD_SET_DIR = 6
|
||||
REQUEST_UPLOAD_FINISHED = 7
|
||||
REQUEST_UPLOAD_CANCELED = 8
|
||||
REQUEST_INDIVIDUAL_FILE_STARTED = 9
|
||||
REQUEST_INDIVIDUAL_FILE_PROGRESS = 10
|
||||
REQUEST_INDIVIDUAL_FILE_CANCELED = 11
|
||||
REQUEST_ERROR_DATA_DIR_CANNOT_CREATE = 12
|
||||
REQUEST_OTHER = 13
|
||||
|
||||
def __init__(self, common, is_gui, mode_settings, mode="share"):
|
||||
self.common = common
|
||||
|
@ -92,8 +89,6 @@ class Web:
|
|||
)
|
||||
self.app.secret_key = self.common.random_string(8)
|
||||
self.generate_static_url_path()
|
||||
self.auth = HTTPBasicAuth()
|
||||
self.auth.error_handler(self.error401)
|
||||
|
||||
# Verbose mode?
|
||||
if self.common.verbose:
|
||||
|
@ -132,9 +127,6 @@ class Web:
|
|||
]
|
||||
|
||||
self.q = queue.Queue()
|
||||
self.password = None
|
||||
|
||||
self.reset_invalid_passwords()
|
||||
|
||||
self.done = False
|
||||
|
||||
|
@ -191,7 +183,6 @@ class Web:
|
|||
self.app.static_url_path = self.static_url_path
|
||||
self.app.add_url_rule(
|
||||
self.static_url_path + "/<path:filename>",
|
||||
endpoint="static",
|
||||
view_func=self.app.send_static_file,
|
||||
)
|
||||
|
||||
|
@ -200,28 +191,6 @@ class Web:
|
|||
Common web app routes between all modes.
|
||||
"""
|
||||
|
||||
@self.auth.get_password
|
||||
def get_pw(username):
|
||||
if username == "onionshare":
|
||||
return self.password
|
||||
else:
|
||||
return None
|
||||
|
||||
@self.app.before_request
|
||||
def conditional_auth_check():
|
||||
# Allow static files without basic authentication
|
||||
if request.path.startswith(self.static_url_path + "/"):
|
||||
return None
|
||||
|
||||
# If public mode is disabled, require authentication
|
||||
if not self.settings.get("general", "public"):
|
||||
|
||||
@self.auth.login_required
|
||||
def _check_login():
|
||||
return None
|
||||
|
||||
return _check_login()
|
||||
|
||||
@self.app.after_request
|
||||
def add_security_headers(r):
|
||||
"""
|
||||
|
@ -276,28 +245,6 @@ class Web:
|
|||
f"{self.common.get_resource_path('static')}/img/favicon.ico"
|
||||
)
|
||||
|
||||
def error401(self):
|
||||
auth = request.authorization
|
||||
if auth:
|
||||
if (
|
||||
auth["username"] == "onionshare"
|
||||
and auth["password"] not in self.invalid_passwords
|
||||
):
|
||||
print(f"Invalid password guess: {auth['password']}")
|
||||
self.add_request(Web.REQUEST_INVALID_PASSWORD, data=auth["password"])
|
||||
|
||||
self.invalid_passwords.append(auth["password"])
|
||||
self.invalid_passwords_count += 1
|
||||
|
||||
if self.invalid_passwords_count == 20:
|
||||
self.add_request(Web.REQUEST_RATE_LIMIT)
|
||||
self.force_shutdown()
|
||||
print(
|
||||
"Someone has made too many wrong attempts to guess your password, so OnionShare has stopped the server. Start sharing again and send the recipient a new address to share."
|
||||
)
|
||||
|
||||
return render_template("401.html", static_url_path=self.static_url_path), 401
|
||||
|
||||
def error403(self):
|
||||
self.add_request(Web.REQUEST_OTHER, request.path)
|
||||
return render_template("403.html", static_url_path=self.static_url_path), 403
|
||||
|
@ -349,21 +296,6 @@ class Web:
|
|||
"""
|
||||
self.q.put({"type": request_type, "path": path, "data": data})
|
||||
|
||||
def generate_password(self, saved_password=None):
|
||||
self.common.log("Web", "generate_password", f"saved_password={saved_password}")
|
||||
if saved_password is not None and saved_password != "":
|
||||
self.password = saved_password
|
||||
self.common.log(
|
||||
"Web",
|
||||
"generate_password",
|
||||
f'saved_password sent, so password is: "{self.password}"',
|
||||
)
|
||||
else:
|
||||
self.password = self.common.build_password()
|
||||
self.common.log(
|
||||
"Web", "generate_password", f'built random password: "{self.password}"'
|
||||
)
|
||||
|
||||
def verbose_mode(self):
|
||||
"""
|
||||
Turn on verbose mode, which will log flask errors to a file.
|
||||
|
@ -373,10 +305,6 @@ class Web:
|
|||
log_handler.setLevel(logging.WARNING)
|
||||
self.app.logger.addHandler(log_handler)
|
||||
|
||||
def reset_invalid_passwords(self):
|
||||
self.invalid_passwords_count = 0
|
||||
self.invalid_passwords = []
|
||||
|
||||
def force_shutdown(self):
|
||||
"""
|
||||
Stop the flask web server, from the context of the flask app.
|
||||
|
@ -433,18 +361,9 @@ class Web:
|
|||
# To stop flask, load http://shutdown:[shutdown_password]@127.0.0.1/[shutdown_password]/shutdown
|
||||
# (We're putting the shutdown_password in the path as well to make routing simpler)
|
||||
if self.running:
|
||||
if self.password:
|
||||
requests.get(
|
||||
f"http://127.0.0.1:{port}/{self.shutdown_password}/shutdown",
|
||||
auth=requests.auth.HTTPBasicAuth("onionshare", self.password),
|
||||
)
|
||||
else:
|
||||
requests.get(
|
||||
f"http://127.0.0.1:{port}/{self.shutdown_password}/shutdown"
|
||||
)
|
||||
|
||||
# Reset any password that was in use
|
||||
self.password = None
|
||||
requests.get(
|
||||
f"http://127.0.0.1:{port}/{self.shutdown_password}/shutdown"
|
||||
)
|
||||
|
||||
def cleanup(self):
|
||||
"""
|
||||
|
|
274
cli/poetry.lock
generated
274
cli/poetry.lock
generated
|
@ -42,7 +42,18 @@ description = "Python package for providing Mozilla's CA Bundle."
|
|||
name = "certifi"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "2020.12.5"
|
||||
version = "2021.5.30"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Foreign Function Interface for Python calling C code."
|
||||
name = "cffi"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "1.14.6"
|
||||
|
||||
[package.dependencies]
|
||||
pycparser = "*"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
|
@ -112,17 +123,6 @@ dev = ["pytest", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinxco
|
|||
docs = ["sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"]
|
||||
dotenv = ["python-dotenv"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Basic and Digest HTTP authentication for Flask routes"
|
||||
name = "flask-httpauth"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "4.4.0"
|
||||
|
||||
[package.dependencies]
|
||||
Flask = "*"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Socket.IO integration for Flask applications"
|
||||
|
@ -161,7 +161,7 @@ marker = "python_version < \"3.8\""
|
|||
name = "importlib-metadata"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
version = "4.0.1"
|
||||
version = "4.4.0"
|
||||
|
||||
[package.dependencies]
|
||||
zipp = ">=0.5"
|
||||
|
@ -210,7 +210,7 @@ description = "Safely add untrusted strings to HTML/XML markup."
|
|||
name = "markupsafe"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
|
||||
[[package]]
|
||||
category = "dev"
|
||||
|
@ -260,11 +260,27 @@ version = "1.10.0"
|
|||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Cryptographic library for Python"
|
||||
name = "pycryptodome"
|
||||
description = "C parser in Python"
|
||||
name = "pycparser"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
version = "3.10.1"
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
version = "2.20"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Python binding to the Networking and Cryptography (NaCl) library"
|
||||
name = "pynacl"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
version = "1.4.0"
|
||||
|
||||
[package.dependencies]
|
||||
cffi = ">=1.4.1"
|
||||
six = "*"
|
||||
|
||||
[package.extras]
|
||||
docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
|
||||
tests = ["pytest (>=3.2.1,<3.3.0 || >3.3.0)", "hypothesis (>=3.27.0)"]
|
||||
|
||||
[[package]]
|
||||
category = "dev"
|
||||
|
@ -367,11 +383,16 @@ version = "1.16.0"
|
|||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Stem is a Python controller library that allows applications to interact with Tor (https://www.torproject.org/)."
|
||||
description = ""
|
||||
name = "stem"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "1.8.0"
|
||||
version = "1.8.1"
|
||||
|
||||
[package.source]
|
||||
reference = "de3d03a03c7ee57c74c80e9c63cb88072d833717"
|
||||
type = "git"
|
||||
url = "https://github.com/onionshare/stem.git"
|
||||
|
||||
[[package]]
|
||||
category = "dev"
|
||||
|
@ -404,7 +425,7 @@ 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.26.4"
|
||||
version = "1.26.5"
|
||||
|
||||
[package.extras]
|
||||
brotli = ["brotlipy (>=0.6.0)"]
|
||||
|
@ -437,7 +458,7 @@ docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
|
|||
testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
|
||||
|
||||
[metadata]
|
||||
content-hash = "e5b4d1dfb1871b971d8240c41fc16cb339246e880c5bf6be07d9303e6156fe93"
|
||||
content-hash = "181891640e59dac730905019444d42ef8e99da0c34c96fb8a616781661bae537"
|
||||
python-versions = "^3.6"
|
||||
|
||||
[metadata.files]
|
||||
|
@ -454,8 +475,55 @@ bidict = [
|
|||
{file = "bidict-0.21.2.tar.gz", hash = "sha256:4fa46f7ff96dc244abfc437383d987404ae861df797e2fd5b190e233c302be09"},
|
||||
]
|
||||
certifi = [
|
||||
{file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"},
|
||||
{file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"},
|
||||
{file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"},
|
||||
{file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"},
|
||||
]
|
||||
cffi = [
|
||||
{file = "cffi-1.14.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c"},
|
||||
{file = "cffi-1.14.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99"},
|
||||
{file = "cffi-1.14.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99f27fefe34c37ba9875f224a8f36e31d744d8083e00f520f133cab79ad5e819"},
|
||||
{file = "cffi-1.14.6-cp27-cp27m-win32.whl", hash = "sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20"},
|
||||
{file = "cffi-1.14.6-cp27-cp27m-win_amd64.whl", hash = "sha256:7bcac9a2b4fdbed2c16fa5681356d7121ecabf041f18d97ed5b8e0dd38a80224"},
|
||||
{file = "cffi-1.14.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7"},
|
||||
{file = "cffi-1.14.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e22dcb48709fc51a7b58a927391b23ab37eb3737a98ac4338e2448bef8559b33"},
|
||||
{file = "cffi-1.14.6-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:aedb15f0a5a5949ecb129a82b72b19df97bbbca024081ed2ef88bd5c0a610534"},
|
||||
{file = "cffi-1.14.6-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:48916e459c54c4a70e52745639f1db524542140433599e13911b2f329834276a"},
|
||||
{file = "cffi-1.14.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f627688813d0a4140153ff532537fbe4afea5a3dffce1f9deb7f91f848a832b5"},
|
||||
{file = "cffi-1.14.6-cp35-cp35m-win32.whl", hash = "sha256:f0010c6f9d1a4011e429109fda55a225921e3206e7f62a0c22a35344bfd13cca"},
|
||||
{file = "cffi-1.14.6-cp35-cp35m-win_amd64.whl", hash = "sha256:57e555a9feb4a8460415f1aac331a2dc833b1115284f7ded7278b54afc5bd218"},
|
||||
{file = "cffi-1.14.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e8c6a99be100371dbb046880e7a282152aa5d6127ae01783e37662ef73850d8f"},
|
||||
{file = "cffi-1.14.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:19ca0dbdeda3b2615421d54bef8985f72af6e0c47082a8d26122adac81a95872"},
|
||||
{file = "cffi-1.14.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d950695ae4381ecd856bcaf2b1e866720e4ab9a1498cba61c602e56630ca7195"},
|
||||
{file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9dc245e3ac69c92ee4c167fbdd7428ec1956d4e754223124991ef29eb57a09d"},
|
||||
{file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b"},
|
||||
{file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb"},
|
||||
{file = "cffi-1.14.6-cp36-cp36m-win32.whl", hash = "sha256:80b06212075346b5546b0417b9f2bf467fea3bfe7352f781ffc05a8ab24ba14a"},
|
||||
{file = "cffi-1.14.6-cp36-cp36m-win_amd64.whl", hash = "sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e"},
|
||||
{file = "cffi-1.14.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5"},
|
||||
{file = "cffi-1.14.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf"},
|
||||
{file = "cffi-1.14.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69"},
|
||||
{file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56"},
|
||||
{file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c"},
|
||||
{file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33791e8a2dc2953f28b8d8d300dde42dd929ac28f974c4b4c6272cb2955cb762"},
|
||||
{file = "cffi-1.14.6-cp37-cp37m-win32.whl", hash = "sha256:0c0591bee64e438883b0c92a7bed78f6290d40bf02e54c5bf0978eaf36061771"},
|
||||
{file = "cffi-1.14.6-cp37-cp37m-win_amd64.whl", hash = "sha256:8eb687582ed7cd8c4bdbff3df6c0da443eb89c3c72e6e5dcdd9c81729712791a"},
|
||||
{file = "cffi-1.14.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0"},
|
||||
{file = "cffi-1.14.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e"},
|
||||
{file = "cffi-1.14.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346"},
|
||||
{file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26bb2549b72708c833f5abe62b756176022a7b9a7f689b571e74c8478ead51dc"},
|
||||
{file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd"},
|
||||
{file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2ad4d668a5c0645d281dcd17aff2be3212bc109b33814bbb15c4939f44181cc"},
|
||||
{file = "cffi-1.14.6-cp38-cp38-win32.whl", hash = "sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548"},
|
||||
{file = "cffi-1.14.6-cp38-cp38-win_amd64.whl", hash = "sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156"},
|
||||
{file = "cffi-1.14.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:06c54a68935738d206570b20da5ef2b6b6d92b38ef3ec45c5422c0ebaf338d4d"},
|
||||
{file = "cffi-1.14.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e"},
|
||||
{file = "cffi-1.14.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c"},
|
||||
{file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202"},
|
||||
{file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f"},
|
||||
{file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9e005e9bd57bc987764c32a1bee4364c44fdc11a3cc20a40b93b444984f2b87"},
|
||||
{file = "cffi-1.14.6-cp39-cp39-win32.whl", hash = "sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728"},
|
||||
{file = "cffi-1.14.6-cp39-cp39-win_amd64.whl", hash = "sha256:818014c754cd3dba7229c0f5884396264d51ffb87ec86e927ef0be140bfdb0d2"},
|
||||
{file = "cffi-1.14.6.tar.gz", hash = "sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd"},
|
||||
]
|
||||
chardet = [
|
||||
{file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"},
|
||||
|
@ -481,10 +549,6 @@ flask = [
|
|||
{file = "Flask-1.1.4-py2.py3-none-any.whl", hash = "sha256:c34f04500f2cbbea882b1acb02002ad6fe6b7ffa64a6164577995657f50aed22"},
|
||||
{file = "Flask-1.1.4.tar.gz", hash = "sha256:0fbeb6180d383a9186d0d6ed954e0042ad9f18e0e8de088b2b419d526927d196"},
|
||||
]
|
||||
flask-httpauth = [
|
||||
{file = "Flask-HTTPAuth-4.4.0.tar.gz", hash = "sha256:bcaaa7a35a3cba0b2eafd4f113b3016bf70eb78087456d96484c3c18928b813a"},
|
||||
{file = "Flask_HTTPAuth-4.4.0-py2.py3-none-any.whl", hash = "sha256:d9131122cdc5709dda63790f6e9b3142d8101447d424b0b95ffd4ee279f49539"},
|
||||
]
|
||||
flask-socketio = [
|
||||
{file = "Flask-SocketIO-5.0.1.tar.gz", hash = "sha256:5c4319f5214ada20807857dc8fdf3dc7d2afe8d6dd38f5c516c72e2be47d2227"},
|
||||
{file = "Flask_SocketIO-5.0.1-py2.py3-none-any.whl", hash = "sha256:5d9a4438bafd806c5a3b832e74b69758781a8ee26fb6c9b1dbdda9b4fced432e"},
|
||||
|
@ -545,8 +609,8 @@ idna = [
|
|||
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
|
||||
]
|
||||
importlib-metadata = [
|
||||
{file = "importlib_metadata-4.0.1-py3-none-any.whl", hash = "sha256:d7eb1dea6d6a6086f8be21784cc9e3bcfa55872b52309bc5fad53a8ea444465d"},
|
||||
{file = "importlib_metadata-4.0.1.tar.gz", hash = "sha256:8c501196e49fb9df5df43833bdb1e4328f64847763ec8a50703148b73784d581"},
|
||||
{file = "importlib_metadata-4.4.0-py3-none-any.whl", hash = "sha256:960d52ba7c21377c990412aca380bf3642d734c2eaab78a2c39319f67c6a5786"},
|
||||
{file = "importlib_metadata-4.4.0.tar.gz", hash = "sha256:e592faad8de1bda9fe920cf41e15261e7131bcf266c30306eec00e8e225c1dd5"},
|
||||
]
|
||||
iniconfig = [
|
||||
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
||||
|
@ -561,40 +625,60 @@ jinja2 = [
|
|||
{file = "Jinja2-2.11.3.tar.gz", hash = "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"},
|
||||
]
|
||||
markupsafe = [
|
||||
{file = "MarkupSafe-2.0.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2efaeb1baff547063bad2b2893a8f5e9c459c4624e1a96644bbba08910ae34e0"},
|
||||
{file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:441ce2a8c17683d97e06447fcbccbdb057cbf587c78eb75ae43ea7858042fe2c"},
|
||||
{file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:45535241baa0fc0ba2a43961a1ac7562ca3257f46c4c3e9c0de38b722be41bd1"},
|
||||
{file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:90053234a6479738fd40d155268af631c7fca33365f964f2208867da1349294b"},
|
||||
{file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3b54a9c68995ef4164567e2cd1a5e16db5dac30b2a50c39c82db8d4afaf14f63"},
|
||||
{file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:f58b5ba13a5689ca8317b98439fccfbcc673acaaf8241c1869ceea40f5d585bf"},
|
||||
{file = "MarkupSafe-2.0.0-cp36-cp36m-win32.whl", hash = "sha256:a00dce2d96587651ef4fa192c17e039e8cfab63087c67e7d263a5533c7dad715"},
|
||||
{file = "MarkupSafe-2.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:007dc055dbce5b1104876acee177dbfd18757e19d562cd440182e1f492e96b95"},
|
||||
{file = "MarkupSafe-2.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a08cd07d3c3c17cd33d9e66ea9dee8f8fc1c48e2d11bd88fd2dc515a602c709b"},
|
||||
{file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:3c352ff634e289061711608f5e474ec38dbaa21e3e168820d53d5f4015e5b91b"},
|
||||
{file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:32200f562daaab472921a11cbb63780f1654552ae49518196fc361ed8e12e901"},
|
||||
{file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:fef86115fdad7ae774720d7103aa776144cf9b66673b4afa9bcaa7af990ed07b"},
|
||||
{file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e79212d09fc0e224d20b43ad44bb0a0a3416d1e04cf6b45fed265114a5d43d20"},
|
||||
{file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:79b2ae94fa991be023832e6bcc00f41dbc8e5fe9d997a02db965831402551730"},
|
||||
{file = "MarkupSafe-2.0.0-cp37-cp37m-win32.whl", hash = "sha256:3261fae28155e5c8634dd7710635fe540a05b58f160cef7713c7700cb9980e66"},
|
||||
{file = "MarkupSafe-2.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e4570d16f88c7f3032ed909dc9e905a17da14a1c4cfd92608e3fda4cb1208bbd"},
|
||||
{file = "MarkupSafe-2.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f806bfd0f218477d7c46a11d3e52dc7f5fdfaa981b18202b7dc84bbc287463b"},
|
||||
{file = "MarkupSafe-2.0.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e77e4b983e2441aff0c0d07ee711110c106b625f440292dfe02a2f60c8218bd6"},
|
||||
{file = "MarkupSafe-2.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:031bf79a27d1c42f69c276d6221172417b47cb4b31cdc73d362a9bf5a1889b9f"},
|
||||
{file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:83cf0228b2f694dcdba1374d5312f2277269d798e65f40344964f642935feac1"},
|
||||
{file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4cc563836f13c57f1473bc02d1e01fc37bab70ad4ee6be297d58c1d66bc819bf"},
|
||||
{file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:d00a669e4a5bec3ee6dbeeeedd82a405ced19f8aeefb109a012ea88a45afff96"},
|
||||
{file = "MarkupSafe-2.0.0-cp38-cp38-win32.whl", hash = "sha256:161d575fa49395860b75da5135162481768b11208490d5a2143ae6785123e77d"},
|
||||
{file = "MarkupSafe-2.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:58bc9fce3e1557d463ef5cee05391a05745fd95ed660f23c1742c711712c0abb"},
|
||||
{file = "MarkupSafe-2.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3fb47f97f1d338b943126e90b79cad50d4fcfa0b80637b5a9f468941dbbd9ce5"},
|
||||
{file = "MarkupSafe-2.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dab0c685f21f4a6c95bfc2afd1e7eae0033b403dd3d8c1b6d13a652ada75b348"},
|
||||
{file = "MarkupSafe-2.0.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:664832fb88b8162268928df233f4b12a144a0c78b01d38b81bdcf0fc96668ecb"},
|
||||
{file = "MarkupSafe-2.0.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:df561f65049ed3556e5b52541669310e88713fdae2934845ec3606f283337958"},
|
||||
{file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:24bbc3507fb6dfff663af7900a631f2aca90d5a445f272db5fc84999fa5718bc"},
|
||||
{file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:87de598edfa2230ff274c4de7fcf24c73ffd96208c8e1912d5d0fee459767d75"},
|
||||
{file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a19d39b02a24d3082856a5b06490b714a9d4179321225bbf22809ff1e1887cc8"},
|
||||
{file = "MarkupSafe-2.0.0-cp39-cp39-win32.whl", hash = "sha256:4aca81a687975b35e3e80bcf9aa93fe10cd57fac37bf18b2314c186095f57e05"},
|
||||
{file = "MarkupSafe-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:70820a1c96311e02449591cbdf5cd1c6a34d5194d5b55094ab725364375c9eb2"},
|
||||
{file = "MarkupSafe-2.0.0.tar.gz", hash = "sha256:4fae0677f712ee090721d8b17f412f1cbceefbf0dc180fe91bab3232f38b4527"},
|
||||
{file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"},
|
||||
{file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38"},
|
||||
{file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad"},
|
||||
{file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d"},
|
||||
{file = "MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646"},
|
||||
{file = "MarkupSafe-2.0.1-cp310-cp310-win32.whl", hash = "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28"},
|
||||
{file = "MarkupSafe-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"},
|
||||
{file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"},
|
||||
{file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"},
|
||||
{file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"},
|
||||
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
|
||||
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
|
||||
]
|
||||
packaging = [
|
||||
{file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"},
|
||||
|
@ -638,37 +722,29 @@ py = [
|
|||
{file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"},
|
||||
{file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"},
|
||||
]
|
||||
pycryptodome = [
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1c5e1ca507de2ad93474be5cfe2bfa76b7cf039a1a32fc196f40935944871a06"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:6260e24d41149268122dd39d4ebd5941e9d107f49463f7e071fd397e29923b0c"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:3f840c49d38986f6e17dbc0673d37947c88bc9d2d9dba1c01b979b36f8447db1"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:2dea65df54349cdfa43d6b2e8edb83f5f8d6861e5cf7b1fbc3e34c5694c85e27"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:e61e363d9a5d7916f3a4ce984a929514c0df3daf3b1b2eb5e6edbb131ee771cf"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:2603c98ae04aac675fefcf71a6c87dc4bb74a75e9071ae3923bbc91a59f08d35"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27m-win32.whl", hash = "sha256:38661348ecb71476037f1e1f553159b80d256c00f6c0b00502acac891f7116d9"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27m-win_amd64.whl", hash = "sha256:1723ebee5561628ce96748501cdaa7afaa67329d753933296321f0be55358dce"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:77997519d8eb8a4adcd9a47b9cec18f9b323e296986528186c0e9a7a15d6a07e"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:99b2f3fc51d308286071d0953f92055504a6ffe829a832a9fc7a04318a7683dd"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:e0a4d5933a88a2c98bbe19c0c722f5483dc628d7a38338ac2cb64a7dbd34064b"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d3d6958d53ad307df5e8469cc44474a75393a434addf20ecd451f38a72fe29b8"},
|
||||
{file = "pycryptodome-3.10.1-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:a8eb8b6ea09ec1c2535bf39914377bc8abcab2c7d30fa9225eb4fe412024e427"},
|
||||
{file = "pycryptodome-3.10.1-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:31c1df17b3dc5f39600a4057d7db53ac372f492c955b9b75dd439f5d8b460129"},
|
||||
{file = "pycryptodome-3.10.1-cp35-abi3-manylinux1_i686.whl", hash = "sha256:a3105a0eb63eacf98c2ecb0eb4aa03f77f40fbac2bdde22020bb8a536b226bb8"},
|
||||
{file = "pycryptodome-3.10.1-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:a92d5c414e8ee1249e850789052608f582416e82422502dc0ac8c577808a9067"},
|
||||
{file = "pycryptodome-3.10.1-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:60386d1d4cfaad299803b45a5bc2089696eaf6cdd56f9fc17479a6f89595cfc8"},
|
||||
{file = "pycryptodome-3.10.1-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:501ab36aae360e31d0ec370cf5ce8ace6cb4112060d099b993bc02b36ac83fb6"},
|
||||
{file = "pycryptodome-3.10.1-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:fc7489a50323a0df02378bc2fff86eb69d94cc5639914346c736be981c6a02e7"},
|
||||
{file = "pycryptodome-3.10.1-cp35-abi3-win32.whl", hash = "sha256:9b6f711b25e01931f1c61ce0115245a23cdc8b80bf8539ac0363bdcf27d649b6"},
|
||||
{file = "pycryptodome-3.10.1-cp35-abi3-win_amd64.whl", hash = "sha256:7fd519b89585abf57bf47d90166903ec7b43af4fe23c92273ea09e6336af5c07"},
|
||||
{file = "pycryptodome-3.10.1-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:09c1555a3fa450e7eaca41ea11cd00afe7c91fef52353488e65663777d8524e0"},
|
||||
{file = "pycryptodome-3.10.1-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:758949ca62690b1540dfb24ad773c6da9cd0e425189e83e39c038bbd52b8e438"},
|
||||
{file = "pycryptodome-3.10.1-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:e3bf558c6aeb49afa9f0c06cee7fb5947ee5a1ff3bd794b653d39926b49077fa"},
|
||||
{file = "pycryptodome-3.10.1-pp27-pypy_73-win32.whl", hash = "sha256:f977cdf725b20f6b8229b0c87acb98c7717e742ef9f46b113985303ae12a99da"},
|
||||
{file = "pycryptodome-3.10.1-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6d2df5223b12437e644ce0a3be7809471ffa71de44ccd28b02180401982594a6"},
|
||||
{file = "pycryptodome-3.10.1-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:98213ac2b18dc1969a47bc65a79a8fca02a414249d0c8635abb081c7f38c91b6"},
|
||||
{file = "pycryptodome-3.10.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:12222a5edc9ca4a29de15fbd5339099c4c26c56e13c2ceddf0b920794f26165d"},
|
||||
{file = "pycryptodome-3.10.1-pp36-pypy36_pp73-win32.whl", hash = "sha256:6bbf7fee7b7948b29d7e71fcacf48bac0c57fb41332007061a933f2d996f9713"},
|
||||
{file = "pycryptodome-3.10.1.tar.gz", hash = "sha256:3e2e3a06580c5f190df843cdb90ea28d61099cf4924334d5297a995de68e4673"},
|
||||
pycparser = [
|
||||
{file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"},
|
||||
{file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"},
|
||||
]
|
||||
pynacl = [
|
||||
{file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"},
|
||||
{file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"},
|
||||
{file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"},
|
||||
{file = "PyNaCl-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"},
|
||||
{file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"},
|
||||
{file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"},
|
||||
{file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"},
|
||||
{file = "PyNaCl-1.4.0-cp35-abi3-win32.whl", hash = "sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634"},
|
||||
{file = "PyNaCl-1.4.0-cp35-abi3-win_amd64.whl", hash = "sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6"},
|
||||
{file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"},
|
||||
{file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"},
|
||||
{file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"},
|
||||
{file = "PyNaCl-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6"},
|
||||
{file = "PyNaCl-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f"},
|
||||
{file = "PyNaCl-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f"},
|
||||
{file = "PyNaCl-1.4.0-cp38-cp38-win32.whl", hash = "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96"},
|
||||
{file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"},
|
||||
{file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"},
|
||||
]
|
||||
pyparsing = [
|
||||
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
|
||||
|
@ -699,9 +775,7 @@ six = [
|
|||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
]
|
||||
stem = [
|
||||
{file = "stem-1.8.0.tar.gz", hash = "sha256:a0b48ea6224e95f22aa34c0bc3415f0eb4667ddeae3dfb5e32a6920c185568c2"},
|
||||
]
|
||||
stem = []
|
||||
toml = [
|
||||
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||
|
@ -716,8 +790,8 @@ unidecode = [
|
|||
{file = "Unidecode-1.2.0.tar.gz", hash = "sha256:8d73a97d387a956922344f6b74243c2c6771594659778744b2dbdaad8f6b727d"},
|
||||
]
|
||||
urllib3 = [
|
||||
{file = "urllib3-1.26.4-py2.py3-none-any.whl", hash = "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df"},
|
||||
{file = "urllib3-1.26.4.tar.gz", hash = "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"},
|
||||
{file = "urllib3-1.26.5-py2.py3-none-any.whl", hash = "sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c"},
|
||||
{file = "urllib3-1.26.5.tar.gz", hash = "sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098"},
|
||||
]
|
||||
werkzeug = [
|
||||
{file = "Werkzeug-1.0.1-py2.py3-none-any.whl", hash = "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43"},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "onionshare_cli"
|
||||
version = "2.3.2"
|
||||
version = "2.3.3"
|
||||
description = "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."
|
||||
authors = ["Micah Lee <micah@micahflee.com>"]
|
||||
license = "GPLv3+"
|
||||
|
@ -18,19 +18,18 @@ classifiers = [
|
|||
[tool.poetry.dependencies]
|
||||
python = "^3.6"
|
||||
click = "*"
|
||||
flask = "^1.1.4"
|
||||
flask-httpauth = "*"
|
||||
flask = "1.1.4"
|
||||
flask-socketio = "5.0.1"
|
||||
psutil = "*"
|
||||
pycryptodome = "*"
|
||||
pysocks = "*"
|
||||
requests = {extras = ["socks"], version = "^2.25.1"}
|
||||
stem = "*"
|
||||
requests = {extras = ["socks"], version = "*"}
|
||||
unidecode = "*"
|
||||
urllib3 = "*"
|
||||
eventlet = "*"
|
||||
setuptools = "*"
|
||||
colorama = "^0.4.4"
|
||||
pynacl = "^1.4.0"
|
||||
colorama = "*"
|
||||
stem = {git = "https://github.com/onionshare/stem.git", rev = "1.8.1"}
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = "*"
|
||||
|
|
|
@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
"""
|
||||
import setuptools
|
||||
|
||||
version = "2.3.2"
|
||||
version = "2.3.3"
|
||||
|
||||
setuptools.setup(
|
||||
name="onionshare-cli",
|
||||
|
|
|
@ -34,6 +34,7 @@ class TestSettings:
|
|||
"tor_bridges_use_meek_lite_azure": False,
|
||||
"tor_bridges_use_custom_bridges": "",
|
||||
"persistent_tabs": [],
|
||||
"theme":0
|
||||
}
|
||||
for key in settings_obj._settings:
|
||||
# Skip locale, it will not always default to the same thing
|
||||
|
|
|
@ -48,7 +48,6 @@ def web_obj(temp_dir, common_obj, mode, num_files=0):
|
|||
common_obj.settings = Settings(common_obj)
|
||||
mode_settings = ModeSettings(common_obj)
|
||||
web = Web(common_obj, False, mode_settings, mode)
|
||||
web.generate_password()
|
||||
web.running = True
|
||||
|
||||
web.cleanup_filenames == []
|
||||
|
@ -75,23 +74,13 @@ class TestWeb:
|
|||
web = web_obj(temp_dir, common_obj, "share", 3)
|
||||
assert web.mode == "share"
|
||||
with web.app.test_client() as c:
|
||||
# Load / without auth
|
||||
# Load /
|
||||
res = c.get("/")
|
||||
res.get_data()
|
||||
assert res.status_code == 401
|
||||
|
||||
# Load / with invalid auth
|
||||
res = c.get("/", headers=self._make_auth_headers("invalid"))
|
||||
res.get_data()
|
||||
assert res.status_code == 401
|
||||
|
||||
# Load / with valid auth
|
||||
res = c.get("/", headers=self._make_auth_headers(web.password))
|
||||
res.get_data()
|
||||
assert res.status_code == 200
|
||||
|
||||
# Download
|
||||
res = c.get("/download", headers=self._make_auth_headers(web.password))
|
||||
res = c.get("/download")
|
||||
res.get_data()
|
||||
assert res.status_code == 200
|
||||
assert (
|
||||
|
@ -107,7 +96,7 @@ class TestWeb:
|
|||
|
||||
with web.app.test_client() as c:
|
||||
# Download the first time
|
||||
res = c.get("/download", headers=self._make_auth_headers(web.password))
|
||||
res = c.get("/download")
|
||||
res.get_data()
|
||||
assert res.status_code == 200
|
||||
assert (
|
||||
|
@ -127,7 +116,7 @@ class TestWeb:
|
|||
|
||||
with web.app.test_client() as c:
|
||||
# Download the first time
|
||||
res = c.get("/download", headers=self._make_auth_headers(web.password))
|
||||
res = c.get("/download")
|
||||
res.get_data()
|
||||
assert res.status_code == 200
|
||||
assert (
|
||||
|
@ -141,18 +130,8 @@ class TestWeb:
|
|||
assert web.mode == "receive"
|
||||
|
||||
with web.app.test_client() as c:
|
||||
# Load / without auth
|
||||
res = c.get("/")
|
||||
res.get_data()
|
||||
assert res.status_code == 401
|
||||
|
||||
# Load / with invalid auth
|
||||
res = c.get("/", headers=self._make_auth_headers("invalid"))
|
||||
res.get_data()
|
||||
assert res.status_code == 401
|
||||
|
||||
# Load / with valid auth
|
||||
res = c.get("/", headers=self._make_auth_headers(web.password))
|
||||
res = c.get("/",)
|
||||
res.get_data()
|
||||
assert res.status_code == 200
|
||||
|
||||
|
@ -171,7 +150,7 @@ class TestWeb:
|
|||
)
|
||||
|
||||
with web.app.test_client() as c:
|
||||
res = c.get("/", headers=self._make_auth_headers(web.password))
|
||||
res = c.get("/")
|
||||
res.get_data()
|
||||
assert res.status_code == 200
|
||||
|
||||
|
@ -180,7 +159,6 @@ class TestWeb:
|
|||
buffered=True,
|
||||
content_type="multipart/form-data",
|
||||
data={"file[]": (BytesIO(b"THIS IS A TEST FILE"), "new_york.jpg")},
|
||||
headers=self._make_auth_headers(web.password),
|
||||
)
|
||||
res.get_data()
|
||||
assert res.status_code == 200
|
||||
|
@ -202,7 +180,6 @@ class TestWeb:
|
|||
buffered=True,
|
||||
content_type="multipart/form-data",
|
||||
data={"text": "you know just sending an anonymous message"},
|
||||
headers=self._make_auth_headers(web.password),
|
||||
)
|
||||
content = res.get_data()
|
||||
assert res.status_code == 200
|
||||
|
@ -237,7 +214,6 @@ class TestWeb:
|
|||
"file[]": (BytesIO(b"THIS IS A TEST FILE"), "new_york.jpg"),
|
||||
"text": "you know just sending an anonymous message",
|
||||
},
|
||||
headers=self._make_auth_headers(web.password),
|
||||
)
|
||||
content = res.get_data()
|
||||
assert res.status_code == 200
|
||||
|
@ -270,7 +246,6 @@ class TestWeb:
|
|||
buffered=True,
|
||||
content_type="multipart/form-data",
|
||||
data={"file[]": (BytesIO(b"THIS IS A TEST FILE"), "new_york.jpg")},
|
||||
headers=self._make_auth_headers(web.password),
|
||||
)
|
||||
content = res.get_data()
|
||||
assert res.status_code == 200
|
||||
|
@ -303,7 +278,6 @@ class TestWeb:
|
|||
buffered=True,
|
||||
content_type="multipart/form-data",
|
||||
data={},
|
||||
headers=self._make_auth_headers(web.password),
|
||||
)
|
||||
content = res.get_data()
|
||||
assert res.status_code == 200
|
||||
|
@ -326,26 +300,6 @@ class TestWeb:
|
|||
res.get_data()
|
||||
assert res.status_code == 200
|
||||
|
||||
def test_public_mode_off(self, temp_dir, common_obj):
|
||||
web = web_obj(temp_dir, common_obj, "receive")
|
||||
web.settings.set("general", "public", False)
|
||||
|
||||
with web.app.test_client() as c:
|
||||
# Load / without auth
|
||||
res = c.get("/")
|
||||
res.get_data()
|
||||
assert res.status_code == 401
|
||||
|
||||
# But static resources should work without auth
|
||||
res = c.get(f"{web.static_url_path}/css/style.css")
|
||||
res.get_data()
|
||||
assert res.status_code == 200
|
||||
|
||||
# Load / with valid auth
|
||||
res = c.get("/", headers=self._make_auth_headers(web.password))
|
||||
res.get_data()
|
||||
assert res.status_code == 200
|
||||
|
||||
def test_cleanup(self, common_obj, temp_dir_1024, temp_file_1024):
|
||||
web = web_obj(temp_dir_1024, common_obj, "share", 3)
|
||||
|
||||
|
@ -356,12 +310,6 @@ class TestWeb:
|
|||
assert os.path.exists(temp_dir_1024) is False
|
||||
assert web.cleanup_filenames == []
|
||||
|
||||
def _make_auth_headers(self, password):
|
||||
auth = base64.b64encode(b"onionshare:" + password.encode()).decode()
|
||||
h = Headers()
|
||||
h.add("Authorization", "Basic " + auth)
|
||||
return h
|
||||
|
||||
|
||||
class TestZipWriterDefault:
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -450,8 +398,7 @@ def live_server(web):
|
|||
proc.start()
|
||||
|
||||
url = "http://127.0.0.1:{}".format(port)
|
||||
auth = base64.b64encode(b"onionshare:" + web.password.encode()).decode()
|
||||
req = Request(url, headers={"Authorization": "Basic {}".format(auth)})
|
||||
req = Request(url)
|
||||
|
||||
attempts = 20
|
||||
while True:
|
||||
|
@ -509,7 +456,7 @@ class TestRangeRequests:
|
|||
url = "/download"
|
||||
|
||||
with web.app.test_client() as client:
|
||||
resp = client.get(url, headers=self._make_auth_headers(web.password))
|
||||
resp = client.get(url)
|
||||
assert resp.headers["ETag"].startswith('"sha256:')
|
||||
assert resp.headers["Accept-Ranges"] == "bytes"
|
||||
assert resp.headers.get("Last-Modified") is not None
|
||||
|
@ -524,7 +471,7 @@ class TestRangeRequests:
|
|||
contents = f.read()
|
||||
|
||||
with web.app.test_client() as client:
|
||||
resp = client.get(url, headers=self._make_auth_headers(web.password))
|
||||
resp = client.get(url)
|
||||
assert resp.status_code == 200
|
||||
assert resp.data == contents
|
||||
|
||||
|
@ -536,7 +483,7 @@ class TestRangeRequests:
|
|||
contents = f.read()
|
||||
|
||||
with web.app.test_client() as client:
|
||||
headers = self._make_auth_headers(web.password)
|
||||
headers = Headers()
|
||||
headers.extend({"Range": "bytes=0-10"})
|
||||
resp = client.get(url, headers=headers)
|
||||
assert resp.status_code == 206
|
||||
|
@ -572,7 +519,7 @@ class TestRangeRequests:
|
|||
contents = f.read()
|
||||
|
||||
with web.app.test_client() as client:
|
||||
headers = self._make_auth_headers(web.password)
|
||||
headers = Headers()
|
||||
resp = client.get(url, headers=headers)
|
||||
assert resp.status_code == 200
|
||||
|
||||
|
@ -587,7 +534,7 @@ class TestRangeRequests:
|
|||
url = "/download"
|
||||
|
||||
with web.app.test_client() as client:
|
||||
headers = self._make_auth_headers(web.password)
|
||||
headers = Headers()
|
||||
resp = client.get(url, headers=headers)
|
||||
assert resp.status_code == 200
|
||||
last_mod = resp.headers["Last-Modified"]
|
||||
|
@ -602,7 +549,7 @@ class TestRangeRequests:
|
|||
url = "/download"
|
||||
|
||||
with web.app.test_client() as client:
|
||||
headers = self._make_auth_headers(web.password)
|
||||
headers = Headers()
|
||||
resp = client.get(url, headers=headers)
|
||||
assert resp.status_code == 200
|
||||
|
||||
|
@ -621,11 +568,6 @@ class TestRangeRequests:
|
|||
resp = client.get(url, headers=headers)
|
||||
assert resp.status_code == 206
|
||||
|
||||
def _make_auth_headers(self, password):
|
||||
auth = base64.b64encode(b"onionshare:" + password.encode()).decode()
|
||||
h = Headers()
|
||||
h.add("Authorization", "Basic " + auth)
|
||||
return h
|
||||
|
||||
@pytest.mark.skipif(sys.platform != "Linux", reason="requires Linux")
|
||||
@check_unsupported("curl", ["--version"])
|
||||
|
@ -638,12 +580,9 @@ class TestRangeRequests:
|
|||
with live_server(web) as url:
|
||||
# Debugging help from `man curl`, on error 33
|
||||
# 33 HTTP range error. The range "command" didn't work.
|
||||
auth_header = self._make_auth_headers(web.password)
|
||||
subprocess.check_call(
|
||||
[
|
||||
"curl",
|
||||
"-H",
|
||||
str(auth_header).strip(),
|
||||
"--output",
|
||||
str(download),
|
||||
"--continue-at",
|
||||
|
@ -663,12 +602,9 @@ class TestRangeRequests:
|
|||
download.write("x" * 10)
|
||||
|
||||
with live_server(web) as url:
|
||||
auth_header = self._make_auth_headers(web.password)
|
||||
subprocess.check_call(
|
||||
[
|
||||
"wget",
|
||||
"--header",
|
||||
str(auth_header).strip(),
|
||||
"--continue",
|
||||
"-O",
|
||||
str(download),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue