| 
									
										
										
										
											2012-12-08 01:28:44 +01:00
										 |  |  | #!/usr/bin/env python | 
					
						
							| 
									
										
										
										
											2013-01-12 17:07:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-01 23:43:20 +02:00
										 |  |  | import sys, os | 
					
						
							|  |  |  | import json, hashlib | 
					
						
							| 
									
										
										
										
											2013-01-12 17:07:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-01 23:43:20 +02:00
										 |  |  | try: | 
					
						
							|  |  |  |     import urllib.request as compat_urllib_request | 
					
						
							|  |  |  | except ImportError: # Python 2 | 
					
						
							|  |  |  |     import urllib2 as compat_urllib_request | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def rsa_verify(message, signature, key): | 
					
						
							|  |  |  |     from struct import pack | 
					
						
							|  |  |  |     from hashlib import sha256 | 
					
						
							|  |  |  |     from sys import version_info | 
					
						
							|  |  |  |     def b(x): | 
					
						
							|  |  |  |         if version_info[0] == 2: return x | 
					
						
							|  |  |  |         else: return x.encode('latin1') | 
					
						
							|  |  |  |     assert(type(message) == type(b(''))) | 
					
						
							|  |  |  |     block_size = 0 | 
					
						
							|  |  |  |     n = key[0] | 
					
						
							|  |  |  |     while n: | 
					
						
							|  |  |  |         block_size += 1 | 
					
						
							|  |  |  |         n >>= 8 | 
					
						
							|  |  |  |     signature = pow(int(signature, 16), key[1], key[0]) | 
					
						
							|  |  |  |     raw_bytes = [] | 
					
						
							|  |  |  |     while signature: | 
					
						
							|  |  |  |         raw_bytes.insert(0, pack("B", signature & 0xFF)) | 
					
						
							|  |  |  |         signature >>= 8 | 
					
						
							|  |  |  |     signature = (block_size - len(raw_bytes)) * b('\x00') + b('').join(raw_bytes) | 
					
						
							|  |  |  |     if signature[0:2] != b('\x00\x01'): return False | 
					
						
							|  |  |  |     signature = signature[2:] | 
					
						
							|  |  |  |     if not b('\x00') in signature: return False | 
					
						
							|  |  |  |     signature = signature[signature.index(b('\x00'))+1:] | 
					
						
							|  |  |  |     if not signature.startswith(b('\x30\x31\x30\x0D\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20')): return False | 
					
						
							|  |  |  |     signature = signature[19:] | 
					
						
							|  |  |  |     if signature != sha256(message).digest(): return False | 
					
						
							|  |  |  |     return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sys.stderr.write(u'Hi! We changed distribution method and now youtube-dl needs to update itself one more time.\n') | 
					
						
							|  |  |  | sys.stderr.write(u'This will only happen once. Simply press enter to go on. Sorry for the trouble!\n') | 
					
						
							| 
									
										
										
										
											2013-04-06 10:46:17 +02:00
										 |  |  | sys.stderr.write(u'From now on, get the binaries from http://rg3.github.io/youtube-dl/download.html, not from the git repository.\n\n') | 
					
						
							| 
									
										
										
										
											2013-04-01 23:43:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  | 	raw_input() | 
					
						
							|  |  |  | except NameError: # Python 3 | 
					
						
							|  |  |  | 	input() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | filename = sys.argv[0] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-06 10:46:17 +02:00
										 |  |  | UPDATE_URL = "http://rg3.github.io/youtube-dl/update/" | 
					
						
							| 
									
										
										
										
											2013-04-01 23:43:20 +02:00
										 |  |  | VERSION_URL = UPDATE_URL + 'LATEST_VERSION' | 
					
						
							|  |  |  | JSON_URL = UPDATE_URL + 'versions.json' | 
					
						
							|  |  |  | UPDATES_RSA_KEY = (0x9d60ee4d8f805312fdb15a62f87b95bd66177b91df176765d13514a0f1754bcd2057295c5b6f1d35daa6742c3ffc9a82d3e118861c207995a8031e151d863c9927e304576bc80692bc8e094896fcf11b66f3e29e04e3a71e9a11558558acea1840aec37fc396fb6b65dc81a1c4144e03bd1c011de62e3f1357b327d08426fe93, 65537) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if not os.access(filename, os.W_OK): | 
					
						
							|  |  |  |     sys.exit('ERROR: no write permissions on %s' % filename) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     versions_info = compat_urllib_request.urlopen(JSON_URL).read().decode('utf-8') | 
					
						
							|  |  |  |     versions_info = json.loads(versions_info) | 
					
						
							|  |  |  | except: | 
					
						
							|  |  |  |     sys.exit(u'ERROR: can\'t obtain versions info. Please try again later.') | 
					
						
							|  |  |  | if not 'signature' in versions_info: | 
					
						
							|  |  |  |     sys.exit(u'ERROR: the versions file is not signed or corrupted. Aborting.') | 
					
						
							|  |  |  | signature = versions_info['signature'] | 
					
						
							|  |  |  | del versions_info['signature'] | 
					
						
							|  |  |  | if not rsa_verify(json.dumps(versions_info, sort_keys=True).encode('utf-8'), signature, UPDATES_RSA_KEY): | 
					
						
							|  |  |  |     sys.exit(u'ERROR: the versions file signature is invalid. Aborting.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | version = versions_info['versions'][versions_info['latest']] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     urlh = compat_urllib_request.urlopen(version['bin'][0]) | 
					
						
							|  |  |  |     newcontent = urlh.read() | 
					
						
							|  |  |  |     urlh.close() | 
					
						
							|  |  |  | except (IOError, OSError) as err: | 
					
						
							|  |  |  |     sys.exit('ERROR: unable to download latest version') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | newcontent_hash = hashlib.sha256(newcontent).hexdigest() | 
					
						
							|  |  |  | if newcontent_hash != version['bin'][1]: | 
					
						
							|  |  |  |     sys.exit(u'ERROR: the downloaded file hash does not match. Aborting.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     with open(filename, 'wb') as outf: | 
					
						
							|  |  |  |         outf.write(newcontent) | 
					
						
							|  |  |  | except (IOError, OSError) as err: | 
					
						
							|  |  |  |     sys.exit('ERROR: unable to overwrite current version') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sys.stderr.write(u'Done! Now you can run youtube-dl.\n') |