Add new option --source-address
Closes #3618, fixes #721, fixes #2481, fixes #4551, closes #1020.
This commit is contained in:
parent
6ce08764a1
commit
be4a824d74
6 changed files with 98 additions and 19 deletions
|
@ -10,6 +10,7 @@ import ctypes
|
|||
import datetime
|
||||
import email.utils
|
||||
import errno
|
||||
import functools
|
||||
import gzip
|
||||
import itertools
|
||||
import io
|
||||
|
@ -34,7 +35,9 @@ from .compat import (
|
|||
compat_chr,
|
||||
compat_getenv,
|
||||
compat_html_entities,
|
||||
compat_http_client,
|
||||
compat_parse_qs,
|
||||
compat_socket_create_connection,
|
||||
compat_str,
|
||||
compat_urllib_error,
|
||||
compat_urllib_parse,
|
||||
|
@ -391,13 +394,14 @@ def formatSeconds(secs):
|
|||
return '%d' % secs
|
||||
|
||||
|
||||
def make_HTTPS_handler(opts_no_check_certificate, **kwargs):
|
||||
def make_HTTPS_handler(params, **kwargs):
|
||||
opts_no_check_certificate = params.get('nocheckcertificate', False)
|
||||
if hasattr(ssl, 'create_default_context'): # Python >= 3.4 or 2.7.9
|
||||
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
if opts_no_check_certificate:
|
||||
context.verify_mode = ssl.CERT_NONE
|
||||
try:
|
||||
return compat_urllib_request.HTTPSHandler(context=context, **kwargs)
|
||||
return YoutubeDLHTTPSHandler(params, context=context, **kwargs)
|
||||
except TypeError:
|
||||
# Python 2.7.8
|
||||
# (create_default_context present but HTTPSHandler has no context=)
|
||||
|
@ -420,17 +424,14 @@ def make_HTTPS_handler(opts_no_check_certificate, **kwargs):
|
|||
except ssl.SSLError:
|
||||
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv23)
|
||||
|
||||
class HTTPSHandlerV3(compat_urllib_request.HTTPSHandler):
|
||||
def https_open(self, req):
|
||||
return self.do_open(HTTPSConnectionV3, req)
|
||||
return HTTPSHandlerV3(**kwargs)
|
||||
return YoutubeDLHTTPSHandler(params, https_conn_class=HTTPSConnectionV3, **kwargs)
|
||||
else: # Python < 3.4
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||
context.verify_mode = (ssl.CERT_NONE
|
||||
if opts_no_check_certificate
|
||||
else ssl.CERT_REQUIRED)
|
||||
context.set_default_verify_paths()
|
||||
return compat_urllib_request.HTTPSHandler(context=context, **kwargs)
|
||||
return YoutubeDLHTTPSHandler(params, context=context, **kwargs)
|
||||
|
||||
|
||||
class ExtractorError(Exception):
|
||||
|
@ -544,6 +545,26 @@ class ContentTooShortError(Exception):
|
|||
self.expected = expected
|
||||
|
||||
|
||||
def _create_http_connection(ydl_handler, http_class, is_https=False, *args, **kwargs):
|
||||
hc = http_class(*args, **kwargs)
|
||||
source_address = ydl_handler._params.get('source_address')
|
||||
if source_address is not None:
|
||||
sa = (source_address, 0)
|
||||
if hasattr(hc, 'source_address'): # Python 2.7+
|
||||
hc.source_address = sa
|
||||
else: # Python 2.6
|
||||
def _hc_connect(self, *args, **kwargs):
|
||||
sock = compat_socket_create_connection(
|
||||
(self.host, self.port), self.timeout, sa)
|
||||
if is_https:
|
||||
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
|
||||
else:
|
||||
self.sock = sock
|
||||
hc.connect = functools.partial(_hc_connect, hc)
|
||||
|
||||
return hc
|
||||
|
||||
|
||||
class YoutubeDLHandler(compat_urllib_request.HTTPHandler):
|
||||
"""Handler for HTTP requests and responses.
|
||||
|
||||
|
@ -562,6 +583,15 @@ class YoutubeDLHandler(compat_urllib_request.HTTPHandler):
|
|||
public domain.
|
||||
"""
|
||||
|
||||
def __init__(self, params, *args, **kwargs):
|
||||
compat_urllib_request.HTTPHandler.__init__(self, *args, **kwargs)
|
||||
self._params = params
|
||||
|
||||
def http_open(self, req):
|
||||
return self.do_open(functools.partial(
|
||||
_create_http_connection, self, compat_http_client.HTTPConnection),
|
||||
req)
|
||||
|
||||
@staticmethod
|
||||
def deflate(data):
|
||||
try:
|
||||
|
@ -631,6 +661,18 @@ class YoutubeDLHandler(compat_urllib_request.HTTPHandler):
|
|||
https_response = http_response
|
||||
|
||||
|
||||
class YoutubeDLHTTPSHandler(compat_urllib_request.HTTPSHandler):
|
||||
def __init__(self, params, https_conn_class=None, *args, **kwargs):
|
||||
compat_urllib_request.HTTPSHandler.__init__(self, *args, **kwargs)
|
||||
self._https_conn_class = https_conn_class or compat_http_client.HTTPSConnection
|
||||
self._params = params
|
||||
|
||||
def https_open(self, req):
|
||||
return self.do_open(functools.partial(
|
||||
_create_http_connection, self, self._https_conn_class, True),
|
||||
req)
|
||||
|
||||
|
||||
def parse_iso8601(date_str, delimiter='T'):
|
||||
""" Return a UNIX timestamp from the given date """
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue