Compare commits
7 Commits
2014.07.10
...
2014.07.11
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
391d53e1dd | ||
|
|
f64ebfe3e5 | ||
|
|
fc040bfd05 | ||
|
|
c8bf86d50d | ||
|
|
61989fb5e9 | ||
|
|
6f9d4d542f | ||
|
|
b3a8878080 |
@@ -33,6 +33,12 @@ _TESTS = [
|
||||
90,
|
||||
u']\\[@?>=<;:/.-,+*)(\'&%$#"hZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjiagfedcb39876',
|
||||
),
|
||||
(
|
||||
u'https://s.ytimg.com/yts/jsbin/html5player-en_US-vflXGBaUN.js',
|
||||
u'js',
|
||||
u'2ACFC7A61CA478CD21425E5A57EBD73DDC78E22A.2094302436B2D377D14A3BBA23022D023B8BC25AA',
|
||||
u'A52CB8B320D22032ABB3A41D773D2B6342034902.A22E87CDD37DBE75A5E52412DC874AC16A7CFCA2',
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@@ -44,7 +50,7 @@ class TestSignature(unittest.TestCase):
|
||||
os.mkdir(self.TESTDATA_DIR)
|
||||
|
||||
|
||||
def make_tfunc(url, stype, sig_length, expected_sig):
|
||||
def make_tfunc(url, stype, sig_input, expected_sig):
|
||||
basename = url.rpartition('/')[2]
|
||||
m = re.match(r'.*-([a-zA-Z0-9_-]+)\.[a-z]+$', basename)
|
||||
assert m, '%r should follow URL format' % basename
|
||||
@@ -66,7 +72,9 @@ def make_tfunc(url, stype, sig_length, expected_sig):
|
||||
with open(fn, 'rb') as testf:
|
||||
swfcode = testf.read()
|
||||
func = ie._parse_sig_swf(swfcode)
|
||||
src_sig = compat_str(string.printable[:sig_length])
|
||||
src_sig = (
|
||||
compat_str(string.printable[:sig_input])
|
||||
if isinstance(sig_input, int) else sig_input)
|
||||
got_sig = func(src_sig)
|
||||
self.assertEqual(got_sig, expected_sig)
|
||||
|
||||
|
||||
@@ -865,71 +865,26 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor):
|
||||
def _decrypt_signature(self, s, video_id, player_url, age_gate=False):
|
||||
"""Turn the encrypted s field into a working signature"""
|
||||
|
||||
if player_url is not None:
|
||||
if player_url.startswith(u'//'):
|
||||
player_url = u'https:' + player_url
|
||||
try:
|
||||
player_id = (player_url, len(s))
|
||||
if player_id not in self._player_cache:
|
||||
func = self._extract_signature_function(
|
||||
video_id, player_url, len(s)
|
||||
)
|
||||
self._player_cache[player_id] = func
|
||||
func = self._player_cache[player_id]
|
||||
if self._downloader.params.get('youtube_print_sig_code'):
|
||||
self._print_sig_code(func, len(s))
|
||||
return func(s)
|
||||
except Exception:
|
||||
tb = traceback.format_exc()
|
||||
self._downloader.report_warning(
|
||||
u'Automatic signature extraction failed: ' + tb)
|
||||
if player_url is None:
|
||||
raise ExtractorError(u'Cannot decrypt signature without player_url')
|
||||
|
||||
self._downloader.report_warning(
|
||||
u'Warning: Falling back to static signature algorithm')
|
||||
|
||||
return self._static_decrypt_signature(
|
||||
s, video_id, player_url, age_gate)
|
||||
|
||||
def _static_decrypt_signature(self, s, video_id, player_url, age_gate):
|
||||
if age_gate:
|
||||
# The videos with age protection use another player, so the
|
||||
# algorithms can be different.
|
||||
if len(s) == 86:
|
||||
return s[2:63] + s[82] + s[64:82] + s[63]
|
||||
|
||||
if len(s) == 93:
|
||||
return s[86:29:-1] + s[88] + s[28:5:-1]
|
||||
elif len(s) == 92:
|
||||
return s[25] + s[3:25] + s[0] + s[26:42] + s[79] + s[43:79] + s[91] + s[80:83]
|
||||
elif len(s) == 91:
|
||||
return s[84:27:-1] + s[86] + s[26:5:-1]
|
||||
elif len(s) == 90:
|
||||
return s[25] + s[3:25] + s[2] + s[26:40] + s[77] + s[41:77] + s[89] + s[78:81]
|
||||
elif len(s) == 89:
|
||||
return s[84:78:-1] + s[87] + s[77:60:-1] + s[0] + s[59:3:-1]
|
||||
elif len(s) == 88:
|
||||
return s[7:28] + s[87] + s[29:45] + s[55] + s[46:55] + s[2] + s[56:87] + s[28]
|
||||
elif len(s) == 87:
|
||||
return s[6:27] + s[4] + s[28:39] + s[27] + s[40:59] + s[2] + s[60:]
|
||||
elif len(s) == 86:
|
||||
return s[80:72:-1] + s[16] + s[71:39:-1] + s[72] + s[38:16:-1] + s[82] + s[15::-1]
|
||||
elif len(s) == 85:
|
||||
return s[3:11] + s[0] + s[12:55] + s[84] + s[56:84]
|
||||
elif len(s) == 84:
|
||||
return s[78:70:-1] + s[14] + s[69:37:-1] + s[70] + s[36:14:-1] + s[80] + s[:14][::-1]
|
||||
elif len(s) == 83:
|
||||
return s[80:63:-1] + s[0] + s[62:0:-1] + s[63]
|
||||
elif len(s) == 82:
|
||||
return s[80:37:-1] + s[7] + s[36:7:-1] + s[0] + s[6:0:-1] + s[37]
|
||||
elif len(s) == 81:
|
||||
return s[56] + s[79:56:-1] + s[41] + s[55:41:-1] + s[80] + s[40:34:-1] + s[0] + s[33:29:-1] + s[34] + s[28:9:-1] + s[29] + s[8:0:-1] + s[9]
|
||||
elif len(s) == 80:
|
||||
return s[1:19] + s[0] + s[20:68] + s[19] + s[69:80]
|
||||
elif len(s) == 79:
|
||||
return s[54] + s[77:54:-1] + s[39] + s[53:39:-1] + s[78] + s[38:34:-1] + s[0] + s[33:29:-1] + s[34] + s[28:9:-1] + s[29] + s[8:0:-1] + s[9]
|
||||
|
||||
else:
|
||||
raise ExtractorError(u'Unable to decrypt signature, key length %d not supported; retrying might work' % (len(s)))
|
||||
if player_url.startswith(u'//'):
|
||||
player_url = u'https:' + player_url
|
||||
try:
|
||||
player_id = (player_url, len(s))
|
||||
if player_id not in self._player_cache:
|
||||
func = self._extract_signature_function(
|
||||
video_id, player_url, len(s)
|
||||
)
|
||||
self._player_cache[player_id] = func
|
||||
func = self._player_cache[player_id]
|
||||
if self._downloader.params.get('youtube_print_sig_code'):
|
||||
self._print_sig_code(func, len(s))
|
||||
return func(s)
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
raise ExtractorError(
|
||||
u'Automatic signature extraction failed: ' + tb, cause=e)
|
||||
|
||||
def _get_available_subtitles(self, video_id, webpage):
|
||||
try:
|
||||
|
||||
@@ -59,7 +59,7 @@ class JSInterpreter(object):
|
||||
if member == 'split("")':
|
||||
return list(val)
|
||||
if member == 'join("")':
|
||||
return u''.join(val)
|
||||
return ''.join(val)
|
||||
if member == 'length':
|
||||
return len(val)
|
||||
if member == 'reverse()':
|
||||
@@ -99,7 +99,7 @@ class JSInterpreter(object):
|
||||
|
||||
def extract_function(self, funcname):
|
||||
func_m = re.search(
|
||||
(r'(?:function %s|%s\s*=\s*function)' % (
|
||||
(r'(?:function %s|[{;]%s\s*=\s*function)' % (
|
||||
re.escape(funcname), re.escape(funcname))) +
|
||||
r'\((?P<args>[a-z,]+)\){(?P<code>[^}]+)}',
|
||||
self.code)
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
|
||||
__version__ = '2014.07.10'
|
||||
__version__ = '2014.07.11'
|
||||
|
||||
Reference in New Issue
Block a user