PEP8 applied
[youtube-dl] / devscripts / transition_helper_exe / youtube-dl.py
1 #!/usr/bin/env python
2
3 import sys, os
4 import urllib2
5 import json, hashlib
6
7
8 def rsa_verify(message, signature, key):
9     from struct import pack
10     from hashlib import sha256
11     from sys import version_info
12
13     def b(x):
14         if version_info[0] == 2:
15             return x
16         else:
17             return x.encode('latin1')
18     assert(type(message) == type(b('')))
19     block_size = 0
20     n = key[0]
21     while n:
22         block_size += 1
23         n >>= 8
24     signature = pow(int(signature, 16), key[1], key[0])
25     raw_bytes = []
26     while signature:
27         raw_bytes.insert(0, pack("B", signature & 0xFF))
28         signature >>= 8
29     signature = (block_size - len(raw_bytes)) * b('\x00') + b('').join(raw_bytes)
30     if signature[0:2] != b('\x00\x01'):
31         return False
32     signature = signature[2:]
33     if not b('\x00') in signature:
34         return False
35     signature = signature[signature.index(b('\x00'))+1:]
36     if not signature.startswith(b('\x30\x31\x30\x0D\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20')):
37         return False
38     signature = signature[19:]
39     if signature != sha256(message).digest():
40         return False
41     return True
42
43 sys.stderr.write(u'Hi! We changed distribution method and now youtube-dl needs to update itself one more time.\n')
44 sys.stderr.write(u'This will only happen once. Simply press enter to go on. Sorry for the trouble!\n')
45 sys.stderr.write(u'From now on, get the binaries from http://rg3.github.com/youtube-dl/download.html, not from the git repository.\n\n')
46
47 raw_input()
48
49 filename = sys.argv[0]
50
51 UPDATE_URL = "http://rg3.github.io/youtube-dl/update/"
52 VERSION_URL = UPDATE_URL + 'LATEST_VERSION'
53 JSON_URL = UPDATE_URL + 'versions.json'
54 UPDATES_RSA_KEY = (0x9d60ee4d8f805312fdb15a62f87b95bd66177b91df176765d13514a0f1754bcd2057295c5b6f1d35daa6742c3ffc9a82d3e118861c207995a8031e151d863c9927e304576bc80692bc8e094896fcf11b66f3e29e04e3a71e9a11558558acea1840aec37fc396fb6b65dc81a1c4144e03bd1c011de62e3f1357b327d08426fe93, 65537)
55
56 if not os.access(filename, os.W_OK):
57     sys.exit('ERROR: no write permissions on %s' % filename)
58
59 exe = os.path.abspath(filename)
60 directory = os.path.dirname(exe)
61 if not os.access(directory, os.W_OK):
62     sys.exit('ERROR: no write permissions on %s' % directory)
63
64 try:
65     versions_info = urllib2.urlopen(JSON_URL).read().decode('utf-8')
66     versions_info = json.loads(versions_info)
67 except:
68     sys.exit(u'ERROR: can\'t obtain versions info. Please try again later.')
69 if not 'signature' in versions_info:
70     sys.exit(u'ERROR: the versions file is not signed or corrupted. Aborting.')
71 signature = versions_info['signature']
72 del versions_info['signature']
73 if not rsa_verify(json.dumps(versions_info, sort_keys=True), signature, UPDATES_RSA_KEY):
74     sys.exit(u'ERROR: the versions file signature is invalid. Aborting.')
75
76 version = versions_info['versions'][versions_info['latest']]
77
78 try:
79     urlh = urllib2.urlopen(version['exe'][0])
80     newcontent = urlh.read()
81     urlh.close()
82 except (IOError, OSError) as err:
83     sys.exit('ERROR: unable to download latest version')
84
85 newcontent_hash = hashlib.sha256(newcontent).hexdigest()
86 if newcontent_hash != version['exe'][1]:
87     sys.exit(u'ERROR: the downloaded file hash does not match. Aborting.')
88
89 try:
90     with open(exe + '.new', 'wb') as outf:
91         outf.write(newcontent)
92 except (IOError, OSError) as err:
93     sys.exit(u'ERROR: unable to write the new version')
94
95 try:
96     bat = os.path.join(directory, 'youtube-dl-updater.bat')
97     b = open(bat, 'w')
98     b.write("""
99 echo Updating youtube-dl...
100 ping 127.0.0.1 -n 5 -w 1000 > NUL
101 move /Y "%s.new" "%s"
102 del "%s"
103     \n""" % (exe, exe, bat))
104     b.close()
105
106     os.startfile(bat)
107 except (IOError, OSError) as err:
108     sys.exit('ERROR: unable to overwrite current version')
109
110 sys.stderr.write(u'Done! Now you can run youtube-dl.\n')