1313__author__ = "Foxlet"
1414__copyright__ = "Copyright 2019, FurCode Project"
1515__license__ = "GPLv3"
16- __version__ = "1.3 "
16+ __version__ = "1.4 "
1717
1818logging .basicConfig (format = '%(asctime)-15s %(message)s' , level = logging .INFO )
1919logger = logging .getLogger ('webactivity' )
@@ -48,48 +48,71 @@ def check_directory(path):
4848 if exception .errno != errno .EEXIST :
4949 raise
5050
51+ @staticmethod
52+ def fetch_plist (url ):
53+ logging .info ("Network Request: %s" , "Fetching {}" .format (url ))
54+ plist_raw = requests .get (url , headers = ClientMeta .swupdate )
55+ plist_data = plist_raw .text .encode ('UTF-8' )
56+ return plist_data
57+
58+ @staticmethod
59+ def parse_plist (catalog_data ):
60+ if sys .version_info > (3 , 0 ):
61+ root = plistlib .loads (catalog_data )
62+ else :
63+ root = plistlib .readPlistFromString (catalog_data )
64+ return root
5165
5266class SoftwareService :
5367 # macOS 10.15 is available in 4 different catalogs from SoftwareScan
54- catalogs = {"CustomerSeed" :"https://swscan.apple.com/content/catalogs/others/index-10.15customerseed-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" ,
55- "DeveloperSeed" :"https://swscan.apple.com/content/catalogs/others/index-10.15seed-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" ,
56- "PublicSeed" :"https://swscan.apple.com/content/catalogs/others/index-10.15beta-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" ,
57- "PublicRelease" :"https://swscan.apple.com/content/catalogs/others/index-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" ,
58- "PublicRelease14" :"https://swscan.apple.com/content/catalogs/others/index-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" ,
59- "PublicRelease13" :"https://swscan.apple.com/content/catalogs/others/index-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" }
60-
61- def __init__ (self , catalog_id ):
62- self .catalog_url = self .catalogs .get (catalog_id , self .catalogs ["PublicRelease" ])
68+ catalogs = {
69+ "10.15" : {
70+ "CustomerSeed" :"https://swscan.apple.com/content/catalogs/others/index-10.15customerseed-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" ,
71+ "DeveloperSeed" :"https://swscan.apple.com/content/catalogs/others/index-10.15seed-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" ,
72+ "PublicSeed" :"https://swscan.apple.com/content/catalogs/others/index-10.15beta-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog" ,
73+ "PublicRelease" :"https://swscan.apple.com/content/catalogs/others/index-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog"
74+ },
75+ "10.14" : {
76+ "PublicRelease" :"https://swscan.apple.com/content/catalogs/others/index-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog"
77+ },
78+ "10.13" : {
79+ "PublicRelease" :"https://swscan.apple.com/content/catalogs/others/index-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog"
80+ }
81+ }
82+
83+ def __init__ (self , version , catalog_id ):
84+ self .version = version
85+ self .catalog_url = self .catalogs .get (version ).get (catalog_id )
6386 self .catalog_data = ""
6487
6588 def getcatalog (self ):
66- logging .info ("Network Request: %s" , "Fetching {}" .format (self .catalog_url ))
67- catalog_raw = requests .get (self .catalog_url , headers = ClientMeta .swupdate )
68- self .catalog_data = catalog_raw .text .encode ('UTF-8' )
69- return catalog_raw .text .encode ('UTF-8' )
89+ self .catalog_data = Filesystem .fetch_plist (self .catalog_url )
90+ return self .catalog_data
7091
7192 def getosinstall (self ):
7293 # Load catalogs based on Py3/2 lib
73- if sys .version_info > (3 , 0 ):
74- root = plistlib .loads (self .catalog_data )
75- else :
76- root = plistlib .readPlistFromString (self .catalog_data )
94+ root = Filesystem .parse_plist (self .catalog_data )
7795
7896 # Iterate to find valid OSInstall packages
7997 ospackages = []
8098 products = root ['Products' ]
8199 for product in products :
82100 if products .get (product , {}).get ('ExtendedMetaInfo' , {}).get ('InstallAssistantPackageIdentifiers' , {}).get ('OSInstall' , {}) == 'com.apple.mpkg.OSInstall' :
83101 ospackages .append (product )
84- return ospackages
102+
103+ # Iterate for an specific version
104+ candidates = []
105+ for product in ospackages :
106+ meta_url = products .get (product , {}).get ('ServerMetadataURL' , {})
107+ if self .version in Filesystem .parse_plist (Filesystem .fetch_plist (meta_url )).get ('CFBundleShortVersionString' , {}):
108+ candidates .append (product )
109+
110+ return candidates
85111
86112
87113class MacOSProduct :
88114 def __init__ (self , catalog , product_id ):
89- if sys .version_info > (3 , 0 ):
90- root = plistlib .loads (catalog )
91- else :
92- root = plistlib .readPlistFromString (catalog )
115+ root = Filesystem .parse_plist (catalog )
93116 products = root ['Products' ]
94117 self .date = root ['IndexDate' ]
95118 self .product = products [product_id ]
@@ -107,28 +130,25 @@ def fetchpackages(self, path, keyword=None):
107130
108131@click .command ()
109132@click .option ('-o' , '--output-dir' , default = "BaseSystem/" , help = "Target directory for package output." )
133+ @click .option ('-v' , '--catalog-version' , default = "10.15" , help = "Version of catalog." )
110134@click .option ('-c' , '--catalog-id' , default = "PublicRelease" , help = "Name of catalog." )
111135@click .option ('-p' , '--product-id' , default = "" , help = "Product ID (as seen in SoftwareUpdate)." )
112- @click .option ('-l' , '--latest' , is_flag = True , help = "Get latest available macOS package." )
113- def fetchmacos (output_dir = "BaseSystem/" , catalog_id = "PublicRelease" , product_id = "" , latest = False ):
136+ def fetchmacos (output_dir = "BaseSystem/" , catalog_version = "10.15" , catalog_id = "PublicRelease" , product_id = "" ):
114137 # Get the remote catalog data
115- remote = SoftwareService (catalog_id )
138+ remote = SoftwareService (catalog_version , catalog_id )
116139 catalog = remote .getcatalog ()
117140
118- # If latest is used, find the latest OSInstall package
119- if latest :
120- product_id = remote .getosinstall ()[- 1 ]
121- else :
122- if product_id == "" :
123- print ("You must provide a Product ID (or pass the -l flag) to continue." )
124- exit (1 )
141+ # If no product is given, find the latest OSInstall product
142+ if product_id == "" :
143+ product_id = remote .getosinstall ()[0 ]
125144
126145 # Fetch the given Product ID
127146 try :
128147 product = MacOSProduct (catalog , product_id )
129148 except KeyError :
130149 print ("Product ID {} could not be found." .format (product_id ))
131150 exit (1 )
151+
132152 logging .info ("Selected macOS Product: {}" .format (product_id ))
133153
134154 # Download package to disk
0 commit comments