public static void Main(string[] args) { // CreateDirectory(...) sometimes fails unless we wait (race condition?) if (Directory.Exists(keyDir)) { Directory.Delete(keyDir, true); } Thread.Sleep(100); Directory.CreateDirectory(keyDir); #if !DEBUG makeBinaryPlists = true; #endif if (makeBinaryPlists) { if (!File.Exists(plutil)) { makeBinaryPlists = false; Console.WriteLine("WARNING: plutil not found! Binary plists will NOT be generated."); } } // TODO: Parse the key page using XPath (action=render) [id tags] EnumerateFirmwareListAndSaveKeys("Firmware/Apple_TV"); //EnumerateFirmwareListAndSaveKeys("Firmware/Apple_Watch"); EnumerateFirmwareListAndSaveKeys("Firmware/iPad"); EnumerateFirmwareListAndSaveKeys("Firmware/iPad_mini"); EnumerateFirmwareListAndSaveKeys("Firmware/iPhone"); EnumerateFirmwareListAndSaveKeys("Firmware/iPod_touch"); // Build version listing PlistDict plistRoot = new PlistDict(); foreach (var deviceList in versionsList) { List <FirmwareVersion> versions = deviceList.Value; PlistArray deviceArr = new PlistArray(new IPlistElement[versions.Count]); for (int i = 0; i < versions.Count; i++) { FirmwareVersion ver = versions[i]; PlistDict versionDict = new PlistDict(); versionDict.Add("Build", new PlistString(ver.Build)); versionDict.Add("Version", new PlistString(ver.Version)); versionDict.Add("Has Keys", new PlistBool(ver.HasKeys)); deviceArr.Set(i, versionDict); } plistRoot.Add(deviceList.Key, deviceArr); } // Save version listing PlistDocument versionDoc = new PlistDocument(plistRoot); string keyListPath = Path.Combine(keyDir, "KeyList.plist"); versionDoc.Save(keyListPath, PlistDocumentType.Xml); ConvertPlist(keyListPath); }
private static IEnumerable <string> ParseTable(XmlNode table, List <FirmwareVersion> versionList) { FixColspans(table); FixRowspans(table); bool isSpecialATVFormat = false; int rowNum = -1; foreach (XmlNode row in table.ChildNodes) { rowNum++; // skip headers if (row.InnerText.Contains("Download URL")) { continue; } if (row.InnerText.Contains("Marketing") && row.InnerText.Contains("Internal")) { isSpecialATVFormat = true; continue; } FirmwareVersion ver = new FirmwareVersion(); XmlNode buildCell = null; if (isSpecialATVFormat) { string marketing = row.ChildNodes[0].InnerText.Trim(); string @internal = row.ChildNodes[1].InnerText.Trim(); if (marketing == @internal) { // Should only be true on ATV-4.3 (8F455 - 2557) Debug.Assert(row.ChildNodes[2].InnerText.Trim() == "2557"); ver.Version = "4.3"; } else { ver.Version = String.Format( "{0}/{1}", marketing, @internal); } buildCell = row.ChildNodes[3]; } else { ver.Version = row.ChildNodes[0].InnerText.Trim(); buildCell = row.ChildNodes[1]; } ver.Build = buildCell.InnerText.Trim(); // Don't add a version we've already seen (FixRowspans(...) causes this) // Example: iPhone 2G 1.0.1 (1C25) and 1.0.2 (1C28) bool isDup = false; foreach (FirmwareVersion testVer in versionList) { if (ver.Build == testVer.Build) { isDup = true; break; } } if (isDup) { continue; } XmlNodeList keyPageUrl = buildCell.SelectNodes(".//@href"); if (keyPageUrl.Count == 0) { // This build doesn't have an IPSW. For now, just add the // version to the list, but don't yield a URL. When adding // support for betas, this logic will need to be redone. ver.HasKeys = false; versionList.Add(ver); continue; } else if (keyPageUrl.Count == 1) { string url = keyPageUrl[0].Value; if (url.Contains("redlink")) { ver.HasKeys = false; versionList.Add(ver); continue; } ver.HasKeys = true; versionList.Add(ver); url = url.Substring(url.IndexOf("/wiki/") + "/wiki/".Length); yield return(url); } else { throw new Exception(); } } }