diff --git a/brigadier b/brigadier index 1b19faa..f77c0eb 100755 --- a/brigadier +++ b/brigadier @@ -1,9 +1,9 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import sys import subprocess -import urllib2 +import urllib.request, urllib.error, urllib.parse import plistlib import re import tempfile @@ -14,7 +14,7 @@ import platform import requests from pprint import pprint -from urllib import urlretrieve +from urllib.request import urlretrieve from xml.dom import minidom VERSION = '0.2.6' @@ -23,7 +23,7 @@ SUCATALOG_URL = 'https://swscan.apple.com/content/catalogs/others/index-11-10.15 SEVENZIP_URL = 'https://www.7-zip.org/a/7z2201-x64.msi' def status(msg): - print "%s\n" % msg + print("%s\n" % msg) def getCommandOutput(cmd): p = subprocess.Popen(cmd, stdout=subprocess.PIPE) @@ -118,9 +118,9 @@ def installBootcamp(msipath): status("Install log output:") with open(logpath, 'r') as logfd: logdata = logfd.read() - print logdata.decode('utf-16') + print(logdata.decode('utf-16')) postInstallConfig() - + def main(): scriptdir = os.path.abspath(os.path.dirname(sys.argv[0])) @@ -147,7 +147,7 @@ according to the post date.") opts, args = o.parse_args() if opts.version: - print VERSION + print(VERSION) sys.exit(0) if opts.install: @@ -182,7 +182,7 @@ when running the installer out of 'system32'." % output_dir) if len(models) > 1: status("Using Mac models: %s." % ', '.join(models)) else: - status("Using Mac model: %s." % ', '.join(models)) + status("Using Mac model: %s." % ', '.join(models)) for model in models: sucatalog_url = SUCATALOG_URL @@ -191,24 +191,25 @@ when running the installer out of 'system32'." % output_dir) plist_path = os.path.join(scriptdir, 'brigadier.plist') if os.path.isfile(plist_path): try: - config_plist = plistlib.readPlist(plist_path) + with open(plist_path, 'rb') as f: + config_plist = plistlib.load(f) except: status("Config plist was found at %s but it could not be read. \ Verify that it is readable and is an XML formatted plist." % plist_path) if config_plist: - if 'CatalogURL' in config_plist.keys(): + if 'CatalogURL' in list(config_plist.keys()): sucatalog_url = config_plist['CatalogURL'] - urlfd = urllib2.urlopen(sucatalog_url) + urlfd = urllib.request.urlopen(sucatalog_url) data = urlfd.read() - p = plistlib.readPlistFromString(data) + p = plistlib.loads(data) allprods = p['Products'] # Get all Boot Camp ESD products bc_prods = [] - for (prod_id, prod_data) in allprods.items(): - if 'ServerMetadataURL' in prod_data.keys(): + for (prod_id, prod_data) in list(allprods.items()): + if 'ServerMetadataURL' in list(prod_data.keys()): bc_match = re.search('BootCamp', prod_data['ServerMetadataURL']) if bc_match: bc_prods.append((prod_id, prod_data)) @@ -216,10 +217,10 @@ when running the installer out of 'system32'." % output_dir) pkg_data = [] re_model = "([a-zA-Z]{4,12}[1-9]{1,2}\,[1-6])" for bc_prod in bc_prods: - if 'English' in bc_prod[1]['Distributions'].keys(): + if 'English' in list(bc_prod[1]['Distributions'].keys()): disturl = bc_prod[1]['Distributions']['English'] - distfd = urllib2.urlopen(disturl) - dist_data = distfd.read() + distfd = urllib.request.urlopen(disturl) + dist_data = distfd.read().decode('utf-8') if re.search(model, dist_data): supported_models = [] pkg_data.append({bc_prod[0]: bc_prod[1]}) @@ -227,9 +228,9 @@ when running the installer out of 'system32'." % output_dir) for supported_model in model_matches_in_dist: supported_models.append(supported_model) status("Model supported in package distribution file at %s." % disturl) - status("Distribution %s supports the following models: %s." % + status("Distribution %s supports the following models: %s." % (bc_prod[0], ", ".join(supported_models))) - + # Ensure we have only one ESD if len(pkg_data) == 0: sys.exit("Couldn't find a Boot Camp ESD for the model %s in the given software update catalog." % model) @@ -239,37 +240,37 @@ when running the installer out of 'system32'." % output_dir) sys.exit("--product-id option is only applicable when multiple ESDs are found for a model.") if len(pkg_data) > 1: # sys.exit("There is more than one ESD product available for this model: %s. " - # "Automically selecting the one with the most recent PostDate.." + # "Automically selecting the one with the most recent PostDate.." # % ", ".join([p.keys()[0] for p in pkg_data])) - print "There is more than one ESD product available for this model:" + print("There is more than one ESD product available for this model:") # Init latest to be epoch start latest_date = datetime.datetime.fromtimestamp(0) chosen_product = None for i, p in enumerate(pkg_data): - product = p.keys()[0] + product = list(p.keys())[0] postdate = p[product].get('PostDate') - print "%s: PostDate %s" % (product, postdate) + print("%s: PostDate %s" % (product, postdate)) if postdate > latest_date: latest_date = postdate chosen_product = product if opts.product_id: - if opts.product_id not in [k.keys()[0] for k in pkg_data]: + if opts.product_id not in [list(k.keys())[0] for k in pkg_data]: sys.exit("Product specified with '--product-id %s' either doesn't exist " "or was not found applicable to models: %s" % (opts.product_id, ", ".join(models))) chosen_product = opts.product_id - print "Selecting manually-chosen product %s." % chosen_product + print("Selecting manually-chosen product %s." % chosen_product) else: - print "Selecting %s as it's the most recently posted." % chosen_product + print("Selecting %s as it's the most recently posted." % chosen_product) for p in pkg_data: - if p.keys()[0] == chosen_product: + if list(p.keys())[0] == chosen_product: selected_pkg = p pkg_data = selected_pkg - pkg_id = pkg_data.keys()[0] - pkg_url = pkg_data.values()[0]['Packages'][0]['URL'] + pkg_id = list(pkg_data.keys())[0] + pkg_url = list(pkg_data.values())[0]['Packages'][0]['URL'] # make a sub-dir in the output_dir here, named by product landing_dir = os.path.join(output_dir, 'BootCamp-' + pkg_id) @@ -364,13 +365,13 @@ when running the installer out of 'system32'." % output_dir) shutil.move(os.path.join(arc_workdir, 'Library/Application Support/BootCamp/WindowsSupport.dmg'), output_file) subprocess.call(['7z','-o{}'.format(landing_dir),'x','WindowsSupport.dmg',]) - + status("Extracted to %s." % output_file) if os.path.exists('/mnt/c/Windows/explorer.exe'): subprocess.call(['/mnt/c/Windows/explorer.exe','.']) else: - print("Platform not supported! ({})".format(platform.system())) + print(("Platform not supported! ({})".format(platform.system()))) pass status("Done.")