This commit is contained in:
ton
2024-10-07 10:13:40 +07:00
parent aa1631742f
commit 3a7d696db6
9729 changed files with 1832837 additions and 161742 deletions

View File

@@ -525,9 +525,13 @@ def urlunsplit(components):
empty query; the RFC states that these are equivalent)."""
scheme, netloc, url, query, fragment, _coerce_result = (
_coerce_args(*components))
if netloc or (scheme and scheme in uses_netloc and url[:2] != '//'):
if netloc:
if url and url[:1] != '/': url = '/' + url
url = '//' + (netloc or '') + url
url = '//' + netloc + url
elif url[:2] == '//':
url = '//' + url
elif scheme and scheme in uses_netloc and (not url or url[:1] == '/'):
url = '//' + url
if scheme:
url = scheme + ':' + url
if query:
@@ -763,42 +767,48 @@ def parse_qsl(qs, keep_blank_values=False, strict_parsing=False,
Returns a list, as G-d intended.
"""
qs, _coerce_result = _coerce_args(qs)
separator, _ = _coerce_args(separator)
if not separator or (not isinstance(separator, (str, bytes))):
if not separator or not isinstance(separator, (str, bytes)):
raise ValueError("Separator must be of type string or bytes.")
if isinstance(qs, str):
if not isinstance(separator, str):
separator = str(separator, 'ascii')
eq = '='
def _unquote(s):
return unquote_plus(s, encoding=encoding, errors=errors)
else:
if not qs:
return []
# Use memoryview() to reject integers and iterables,
# acceptable by the bytes constructor.
qs = bytes(memoryview(qs))
if isinstance(separator, str):
separator = bytes(separator, 'ascii')
eq = b'='
def _unquote(s):
return unquote_to_bytes(s.replace(b'+', b' '))
if not qs:
return []
# If max_num_fields is defined then check that the number of fields
# is less than max_num_fields. This prevents a memory exhaustion DOS
# attack via post bodies with many fields.
if max_num_fields is not None:
num_fields = 1 + qs.count(separator) if qs else 0
num_fields = 1 + qs.count(separator)
if max_num_fields < num_fields:
raise ValueError('Max number of fields exceeded')
r = []
query_args = qs.split(separator) if qs else []
for name_value in query_args:
if not name_value and not strict_parsing:
continue
nv = name_value.split('=', 1)
if len(nv) != 2:
if strict_parsing:
for name_value in qs.split(separator):
if name_value or strict_parsing:
name, has_eq, value = name_value.partition(eq)
if not has_eq and strict_parsing:
raise ValueError("bad query field: %r" % (name_value,))
# Handle case of a control-name with no equal sign
if keep_blank_values:
nv.append('')
else:
continue
if len(nv[1]) or keep_blank_values:
name = nv[0].replace('+', ' ')
name = unquote(name, encoding=encoding, errors=errors)
name = _coerce_result(name)
value = nv[1].replace('+', ' ')
value = unquote(value, encoding=encoding, errors=errors)
value = _coerce_result(value)
r.append((name, value))
if value or keep_blank_values:
name = _unquote(name)
value = _unquote(value)
r.append((name, value))
return r
def unquote_plus(string, encoding='utf-8', errors='replace'):

View File

@@ -2589,6 +2589,7 @@ def _proxy_bypass_macosx_sysconf(host, proxy_settings):
}
"""
from fnmatch import fnmatch
from ipaddress import AddressValueError, IPv4Address
hostonly, port = _splitport(host)
@@ -2605,20 +2606,17 @@ def _proxy_bypass_macosx_sysconf(host, proxy_settings):
return True
hostIP = None
try:
hostIP = int(IPv4Address(hostonly))
except AddressValueError:
pass
for value in proxy_settings.get('exceptions', ()):
# Items in the list are strings like these: *.local, 169.254/16
if not value: continue
m = re.match(r"(\d+(?:\.\d+)*)(/\d+)?", value)
if m is not None:
if hostIP is None:
try:
hostIP = socket.gethostbyname(hostonly)
hostIP = ip2num(hostIP)
except OSError:
continue
if m is not None and hostIP is not None:
base = ip2num(m.group(1))
mask = m.group(2)
if mask is None:
@@ -2641,6 +2639,31 @@ def _proxy_bypass_macosx_sysconf(host, proxy_settings):
return False
# Same as _proxy_bypass_macosx_sysconf, testable on all platforms
def _proxy_bypass_winreg_override(host, override):
"""Return True if the host should bypass the proxy server.
The proxy override list is obtained from the Windows
Internet settings proxy override registry value.
An example of a proxy override value is:
"www.example.com;*.example.net; 192.168.0.1"
"""
from fnmatch import fnmatch
host, _ = _splitport(host)
proxy_override = override.split(';')
for test in proxy_override:
test = test.strip()
# "<local>" should bypass the proxy server for all intranet addresses
if test == '<local>':
if '.' not in host:
return True
elif fnmatch(host, test):
return True
return False
if sys.platform == 'darwin':
from _scproxy import _get_proxy_settings, _get_proxies
@@ -2739,7 +2762,7 @@ elif os.name == 'nt':
import winreg
except ImportError:
# Std modules, so should be around - but you never know!
return 0
return False
try:
internetSettings = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
r'Software\Microsoft\Windows\CurrentVersion\Internet Settings')
@@ -2749,40 +2772,10 @@ elif os.name == 'nt':
'ProxyOverride')[0])
# ^^^^ Returned as Unicode but problems if not converted to ASCII
except OSError:
return 0
return False
if not proxyEnable or not proxyOverride:
return 0
# try to make a host list from name and IP address.
rawHost, port = _splitport(host)
host = [rawHost]
try:
addr = socket.gethostbyname(rawHost)
if addr != rawHost:
host.append(addr)
except OSError:
pass
try:
fqdn = socket.getfqdn(rawHost)
if fqdn != rawHost:
host.append(fqdn)
except OSError:
pass
# make a check value list from the registry entry: replace the
# '<local>' string by the localhost entry and the corresponding
# canonical entry.
proxyOverride = proxyOverride.split(';')
# now check if we match one of the registry values.
for test in proxyOverride:
if test == '<local>':
if '.' not in rawHost:
return 1
test = test.replace(".", r"\.") # mask dots
test = test.replace("*", r".*") # change glob sequence
test = test.replace("?", r".") # change glob char
for val in host:
if re.match(test, val, re.I):
return 1
return 0
return False
return _proxy_bypass_winreg_override(host, proxyOverride)
def proxy_bypass(host):
"""Return True, if host should be bypassed.