diff options
| -rw-r--r-- | devscripts/youtube_genalgo.py | 12 | ||||
| -rw-r--r-- | test/test_youtube_sig.py | 11 | ||||
| -rw-r--r-- | youtube_dl/extractor/youtube.py | 18 | 
3 files changed, 35 insertions, 6 deletions
diff --git a/devscripts/youtube_genalgo.py b/devscripts/youtube_genalgo.py index 22977ccd9..fd0120650 100644 --- a/devscripts/youtube_genalgo.py +++ b/devscripts/youtube_genalgo.py @@ -17,9 +17,9 @@ tests = [      # 87 - vflART1Nf 2013/07/24      ("qwertyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!@#$^&*()_-+={[]}|:;?/>.<",       "tyuioplkjhgfdsazxcv<nm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!@#$^&*()_-+={[]}|:;?/>"), -    # 86 - vfl_ymO4Z 2013/06/27 +    # 86 - vflm_D8eE 2013/07/31      ("qwertyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!@#$%^&*()_-+={[|};?/>.<", -     "ertyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!/#$%^&*()_-+={[|};?@"), +     ">.1}|[{=+-_)(*&^%$#@!MNBVCXZASDFGHJK<POIUYTREW509876L432/mnbvcxzasdfghjklpoiuytre"),      # 85 - vflSAFCP9 2013/07/19      ("qwertyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!@#$%^&*()_-+={[};?/>.<",       "ertyuiqplkjhgfdsazx$vbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!@#<%^&*()_-+={[};?/c"), @@ -40,6 +40,12 @@ tests = [       "Z?;}[{=+-(*&^%$#@!MNBVCXRASDFGHKLPOIUYT/EWQ0q87659321mnbvcxzasdfghjkl4oiuytrewp"),  ] +tests_age_gate = [ +    # 86 - vflqinMWD +    ("qwertyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!@#$%^&*()_-+={[|};?/>.<", +     "ertyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!/#$%^&*()_-+={[|};?@"), +] +  def find_matching(wrong, right):      idxs = [wrong.index(c) for c in right]      return compress(idxs) @@ -90,6 +96,8 @@ def genall(tests):  def main():      print(genall(tests)) +    print(u'    Age gate:') +    print(genall(tests_age_gate))  if __name__ == '__main__':      main() diff --git a/test/test_youtube_sig.py b/test/test_youtube_sig.py index 4d45a0e08..d06f3c8aa 100644 --- a/test/test_youtube_sig.py +++ b/test/test_youtube_sig.py @@ -10,7 +10,9 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))  from youtube_dl.extractor.youtube import YoutubeIE  from helper import FakeYDL -sig = YoutubeIE(FakeYDL())._decrypt_signature +ie = YoutubeIE(FakeYDL()) +sig = ie._decrypt_signature +sig_age_gate = ie._decrypt_signature_age_gate  class TestYoutubeSig(unittest.TestCase):      def test_92(self): @@ -35,7 +37,7 @@ class TestYoutubeSig(unittest.TestCase):      def test_86(self):          wrong = "qwertyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!@#$%^&*()_-+={[|};?/>.<" -        right = "ertyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!/#$%^&*()_-+={[|};?@" +        right = ">.1}|[{=+-_)(*&^%$#@!MNBVCXZASDFGHJK<POIUYTREW509876L432/mnbvcxzasdfghjklpoiuytre"          self.assertEqual(sig(wrong), right)      def test_85(self): @@ -67,6 +69,11 @@ class TestYoutubeSig(unittest.TestCase):          wrong = "qwertyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKHGFDSAZXCVBNM!@#$%^&*(-+={[};?/"          right = "Z?;}[{=+-(*&^%$#@!MNBVCXRASDFGHKLPOIUYT/EWQ0q87659321mnbvcxzasdfghjkl4oiuytrewp"          self.assertEqual(sig(wrong), right) +     +    def test_86_age_gate(self): +        wrong = "qwertyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!@#$%^&*()_-+={[|};?/>.<" +        right = "ertyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM!/#$%^&*()_-+={[|};?@" +        self.assertEqual(sig_age_gate(wrong), right)  if __name__ == '__main__':      unittest.main() diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index f10f2e3dd..ba8fdfdf2 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -286,7 +286,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):          elif len(s) == 87:              return s[4:23] + s[86] + s[24:85]          elif len(s) == 86: -            return s[2:63] + s[82] + s[64:82] + s[63] +            return s[83:85] + s[26] + s[79:46:-1] + s[85] + s[45:36:-1] + s[30] + s[35:30:-1] + s[46] + s[29:26:-1] + s[82] + s[25:1:-1]          elif len(s) == 85:              return s[2:8] + s[0] + s[9:21] + s[65] + s[22:65] + s[84] + s[66:82] + s[21]          elif len(s) == 84: @@ -303,6 +303,16 @@ class YoutubeIE(YoutubeBaseInfoExtractor):          else:              raise ExtractorError(u'Unable to decrypt signature, key length %d not supported; retrying might work' % (len(s))) +    def _decrypt_signature_age_gate(self, s): +        # 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] +        else: +            # Fallback to the other algortihms +            self._decrypt_signature(s) + +      def _get_available_subtitles(self, video_id):          self.report_video_subtitles_download(video_id)          request = compat_urllib_request.Request('http://video.google.com/timedtext?hl=en&type=list&v=%s' % video_id) @@ -611,7 +621,11 @@ class YoutubeIE(YoutubeBaseInfoExtractor):                              parts_sizes = u'.'.join(compat_str(len(part)) for part in s.split('.'))                              self.to_screen(u'encrypted signature length %d (%s), itag %s, %s' %                                  (len(s), parts_sizes, url_data['itag'][0], player)) -                        signature = self._decrypt_signature(url_data['s'][0]) +                        encrypted_sig = url_data['s'][0] +                        if age_gate: +                            signature = self._decrypt_signature_age_gate(encrypted_sig) +                        else: +                            signature = self._decrypt_signature(encrypted_sig)                          url += '&signature=' + signature                      if 'ratebypass' not in url:                          url += '&ratebypass=yes'  | 
