public static Title processFile(string filename) { log?.WriteLine("\nProcessing file {0}", filename); try { Title title = processXci(filename) ?? processNsp(filename) ?? processNro(filename); title.filename = filename; title.filesize = new FileInfo(filename).Length; return(title); } catch (MissingKeyException ex) { log?.WriteLine("Missing {0}: {1}", ex.Type == KeyType.Title ? "Title Key" : "Key", ex.Name.Replace("key_area_key_application", "master_key")); } catch (NullReferenceException ex) { log?.WriteLine(ex.StackTrace); log?.WriteLine("\nFile {0} has failed to process", filename); } return(null); }
public static Title processNro(string filename) { Title title = new Title(); using (var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { Nro nro; try { nro = new Nro(filestream.AsStorage()); title.distribution = Title.Distribution.Homebrew; log?.WriteLine("Processing NRO {0}", filename); using (var control = nro.OpenNacp().AsStream()) { processControlNacp(control, ref title); } } catch (InvalidDataException) { return(null); } } log?.WriteLine("NRO information for {0}: [{1}] {2}", filename, title.titleName, title.displayVersion); return(title); }
private static void processControlNacp(Stream controlNacp, ref Title title) { log?.WriteLine("Processing Control NACP"); Nacp nacp = new Nacp(controlNacp); bool first = true; foreach (NacpDescription description in nacp.Descriptions) { if (!String.IsNullOrEmpty(description.Title)) { if (first) { title.titleName = description.Title; title.publisher = description.Developer; first = false; } title.languages.Add(Title.LanguageCode.ElementAtOrDefault((int)description.Language)); } } title.displayVersion = nacp.DisplayVersion; }
static List <Title> openSDCard(string pathSd) { Process.log?.WriteLine("\nOpen SD Card"); List <FsTitle> fsTitles = Process.processSd(pathSd); List <Title> titles = new List <Title>(); if (fsTitles != null) { foreach (var fsTitle in fsTitles) { Title title = Process.processTitle(fsTitle); if (title != null) { titles.Add(title); } } Process.log?.WriteLine("\n{0} titles processed", titles.Count); } else { string error = "SD card \"Contents\" directory could not be found"; Process.log?.WriteLine(error); Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Error.WriteLine(error); Console.ResetColor(); } return(titles); }
static List <Title> openDirectory(string path) { Process.log?.WriteLine("\nOpen Directory"); List <string> filenames = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories) .Where(filename => filename.ToLower().EndsWith(".xci") || filename.ToLower().EndsWith(".nsp") || filename.ToLower().EndsWith(".nro") || (Common.Settings.Default.NszExtension && (filename.ToLower().EndsWith(".xcz") || filename.ToLower().EndsWith(".nsz")))).ToList(); filenames.Sort(); Process.log?.WriteLine("{0} files selected", filenames.Count); Console.Error.WriteLine("Opening {0} files from directory {1}", filenames.Count, path); List <Title> titles = new List <Title>(); foreach (string filename in filenames) { Title title = Process.processFile(filename); if (title != null) { titles.Add(title); } } Process.log?.WriteLine("\n{0} titles processed", titles.Count); return(titles); }
private static void processBiggestNca(Nca nca, ref Title title) { log?.WriteLine("Processing Biggest NCA"); if (((title.type == TitleType.Application || title.type == TitleType.Patch) && nca.Header.ContentType == ContentType.Program) || (title.type == TitleType.Patch && nca.Header.ContentType == ContentType.Data) || (title.type == TitleType.AddOnContent && nca.Header.ContentType == ContentType.AocData)) { title.signature = (nca.Header.FixedSigValidity == Validity.Valid); } if (nca.HasRightsId) { if (keyset.TitleNames.TryGetValue(nca.Header.RightsId, out string titleName)) { title.titleName = titleName; } if (keyset.TitleVersions.TryGetValue(nca.Header.RightsId, out uint titleVersion)) { title.latestVersion = titleVersion; } } else { if (titleNames.TryGetValue(title.titleID, out string titleName)) { title.titleName = titleName; } else if (titleNames.TryGetValue(title.titleIDApplication, out titleName)) { title.titleName = titleName; if (title.type == TitleType.AddOnContent) { title.titleName += " [DLC]"; } } if (titleVersions.TryGetValue(title.titleID, out uint titleVersion)) { title.latestVersion = titleVersion; } } if (((title.type == TitleType.Application || title.type == TitleType.Patch) && nca.Header.ContentType == ContentType.Program) || (title.type == TitleType.Patch && nca.Header.ContentType == ContentType.Data) || (title.type == TitleType.AddOnContent && nca.Header.ContentType == ContentType.AocData)) { title.masterkey = (uint)nca.Header.CryptoType == 2 ? (uint)Math.Max(nca.Header.CryptoType2 - 1, 0) : 0; if (nca.Header.ContentType == ContentType.Program) { processNpdm(nca, ref title); } } }
static Title openFile(string filename) { Process.log?.WriteLine("\nOpen File"); Process.log?.WriteLine("File selected"); Console.Error.WriteLine("Opening file {0}", filename); Title title = Process.processFile(filename); Process.log?.WriteLine("\nTitle processed"); return(title); }
private static void processControlNacp(Stream controlNacp, ref Title title) { log?.WriteLine("Processing Control NACP"); Nacp nacp = new Nacp(controlNacp); foreach (NacpDescription description in nacp.Descriptions) { if (!String.IsNullOrEmpty(description.Title)) { title.titleName = description.Title; break; } } title.displayVersion = nacp.DisplayVersion; }
private static void processNpdm(Nca nca, ref Title title) { log?.WriteLine("Processing NPDM"); try { nca.ParseNpdm(); } catch (MissingKeyException ex) { title.error = String.Format("Missing {0}: {1}", ex.Type == KeyType.Title ? "Title Key" : "Key", ex.Name.Replace("key_area_key_application", "master_key")); log?.WriteLine(title.error); } catch { } if (nca.Npdm != null) { if (nca.Npdm.AciD.ServiceAccess.Services.Count == 0 || nca.Npdm.AciD.ServiceAccess.Services.Keys.Any(key => key.StartsWith("fsp-"))) { log?.WriteLine("Permissions Bitmask 0x{0:x16}", nca.Npdm.AciD.FsAccess.PermissionsBitmask); if (nca.Npdm.AciD.FsAccess.PermissionsBitmask == 0xffffffffffffffff) { title.permission = Title.Permission.Dangerous; } else if ((nca.Npdm.AciD.FsAccess.PermissionsBitmask & 0x8000000000000000) != 0) { title.permission = Title.Permission.Unsafe; } else { title.permission = Title.Permission.Safe; } } else { title.permission = Title.Permission.Safe; } } }
public static Title processFile(string filename) { log?.WriteLine("\nProcessing file {0}", filename); try { Title title = processXci(filename) ?? processNsp(filename) ?? processNro(filename); title.filename = filename; title.filesize = new FileInfo(filename).Length; string titleID = title.type == TitleType.AddOnContent ? title.titleID : title.baseTitleID ?? ""; if (latestVersions.TryGetValue(titleID, out uint version)) { if (title.version > version) { latestVersions[titleID] = title.version; } } else { latestVersions.Add(titleID, title.version); } return(title); } catch (MissingKeyException ex) { log?.WriteLine("Missing {0}: {1}", ex.Type == KeyType.Title ? "Title Key" : "Key", ex.Name.Replace("key_area_key_application", "master_key")); } catch (SystemException ex) when(ex is NullReferenceException || ex is ArgumentException) { log?.WriteLine(ex.StackTrace); log?.WriteLine("\nFile {0} has failed to process", filename); } return(null); }
private static void processNacpXml(IStorage nacpXml, ref Title title) { log?.WriteLine("Processing NACP XML"); Stream stream = nacpXml.AsStream(); byte[] buffer = new byte[stream.Length]; stream.Read(buffer, 0, buffer.Length); stream.Close(); byte[] bom = Encoding.UTF8.GetPreamble(); if (buffer.Take(bom.Length).SequenceEqual(bom)) { Array.Copy(buffer, bom.Length, buffer, 0, buffer.Length - bom.Length); Array.Resize(ref buffer, buffer.Length - bom.Length); } XDocument xml = XDocument.Parse(Encoding.UTF8.GetString(buffer).Replace("&", "&")); title.titleName = xml.Element("Application").Element("Title").Element("Name").Value; title.displayVersion = xml.Element("Application").Element("DisplayVersion").Value; }
public void reloadData() { uint index = 0, count = (uint)titles.Count; objectListView.SetObjects(titles); foreach (OLVListItem listItem in objectListView.Items) { Title title = listItem.RowObject as Title; progressDialog?.SetLine(2, title.titleName, true, IntPtr.Zero); progressDialog?.SetProgress(index++, count); string titleID = title.type == TitleType.AddOnContent ? title.titleID : title.baseTitleID ?? ""; Process.latestVersions.TryGetValue(titleID, out uint latestVersion); Process.versionList.TryGetValue(titleID, out uint version); Process.titleVersions.TryGetValue(titleID, out uint titleVersion); if (latestVersion < version || latestVersion < titleVersion) { listItem.BackColor = title.signature != true ? Color.OldLace : Color.LightYellow; } else if (title.signature != true) { listItem.BackColor = Color.WhiteSmoke; } if (title.permission == Title.Permission.Dangerous) { listItem.ForeColor = Color.DarkRed; } else if (title.permission == Title.Permission.Unsafe) { listItem.ForeColor = Color.Indigo; } } }
private static void processControlNca(Nca nca, ref Title title) { log?.WriteLine("Processing Control NCA"); if (nca.Header.ContentType == ContentType.Control) { title.titleID = String.Format("{0:X16}", nca.Header.TitleId); if (title.type == TitleType.Patch) { title.titleID = title.titleID.Substring(0, Math.Min(title.titleID.Length, 13)) + "800"; } try { Romfs romfs = new Romfs(nca.OpenSection(0, false, IntegrityCheckLevel.ErrorOnInvalid, true)); RomfsFile[] romfsFiles = romfs.Files.ToArray(); foreach (RomfsFile romfsFile in romfsFiles) { if (romfsFile.Name.Equals("control.nacp")) { using (var control = romfs.OpenFile(romfsFile).AsStream()) { processControlNacp(control, ref title); } } } } catch (MissingKeyException ex) { title.error = String.Format("Missing {0}: {1}", ex.Type == KeyType.Title ? "Title Key" : "Key", ex.Name.Replace("key_area_key_application", "master_key")); log?.WriteLine(title.error); } catch (FileNotFoundException) { } } }
private void backgroundWorkerProcess_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) { if (e.Result is List <Title> titles) { objectListView.SetObjects(titles); foreach (OLVListItem listItem in objectListView.Items) { Title title = listItem.RowObject as Title; if (title.signature != true) { listItem.BackColor = Color.WhiteSmoke; } if (title.permission == Title.Permission.Dangerous) { listItem.ForeColor = Color.DarkRed; } else if (title.permission == Title.Permission.Unsafe) { listItem.ForeColor = Color.Indigo; } } toolStripStatusLabel.Text = String.Format("{0} files", titles.Count); progressDialog.StopProgressDialog(); Activate(); } else if (e.Result is string error) { progressDialog.StopProgressDialog(); MessageBox.Show(String.Format("{0}.", error), Application.ProductName); } }
private static void processBiggestNca(IStorage biggestNca, ref Title title) { Nca nca = new Nca(keyset, biggestNca, false); processBiggestNca(nca, ref title); }
private static (string, string) processCnmtNca(Nca nca, ref Title title, bool cnmtContent = true) { string biggestNca = null, controlNca = null; log?.WriteLine("Processing CNMT NCA"); try { Pfs ncaPfs = new Pfs(nca.OpenSection(0, false, IntegrityCheckLevel.ErrorOnInvalid, true)); PfsFileEntry[] ncaFileEntries = ncaPfs.Files; foreach (PfsFileEntry pfsEntry in ncaFileEntries) { Cnmt cnmt = new Cnmt(ncaPfs.OpenFile(pfsEntry).AsStream()); if (title.version == unchecked ((uint)-1) || cnmt.TitleVersion?.Version > title.version) { title.type = cnmt.Type; title.titleID = String.Format("{0:X16}", cnmt.TitleId); title.baseTitleID = String.Format("{0:X16}", cnmt.ApplicationTitleId); title.version = cnmt.TitleVersion?.Version ?? title.version; title.systemVersion = cnmt.MinimumSystemVersion?.Version ?? unchecked ((uint)-1); title.applicationVersion = cnmt.MinimumApplicationVersion?.Version ?? unchecked ((uint)-1); if (cnmtContent) { CnmtContentEntry[] contentEntries = cnmt.ContentEntries; foreach (CnmtContentEntry contentEntry in contentEntries) { if (title.type == TitleType.Application || title.type == TitleType.Patch) { if (contentEntry.Type == CnmtContentType.Program) { biggestNca = BitConverter.ToString(contentEntry.NcaId).Replace("-", "").ToLower() + ".nca"; log?.WriteLine("Found Biggest NCA {0}", biggestNca); } else if (contentEntry.Type == CnmtContentType.Control) { controlNca = BitConverter.ToString(contentEntry.NcaId).Replace("-", "").ToLower() + ".nca"; log?.WriteLine("Found Control NCA {0}", controlNca); } } else if (title.type == TitleType.AddOnContent) { if (contentEntry.Type == CnmtContentType.Data) { biggestNca = BitConverter.ToString(contentEntry.NcaId).Replace("-", "").ToLower() + ".nca"; log?.WriteLine("Found Biggest NCA {0}", biggestNca); } } } } } } } catch (MissingKeyException ex) { title.error = String.Format("Missing {0}: {1}", ex.Type == KeyType.Title ? "Title Key" : "Key", ex.Name.Replace("key_area_key_application", "master_key")); log?.WriteLine(title.error); } catch (FileNotFoundException) { } return(biggestNca, controlNca); }
private static (string, string) processCnmtNca(IStorage cnmtNca, ref Title title) { Nca nca = new Nca(keyset, cnmtNca, false); return(processCnmtNca(nca, ref title)); }
public static Title processTitle(FsTitle fsTitle) { log?.WriteLine("\nProcessing title [{0:X16}] {1}", fsTitle.Id, fsTitle.Name); Title title = new Title { titleID = String.Format("{0:X16}", fsTitle.Id), type = fsTitle.Metadata.Type, filesize = fsTitle.GetSize(), distribution = Title.Distribution.Filesystem }; foreach (Nca nca in fsTitle.Ncas) { if (nca.Header.ContentType == ContentType.Program) { title.filename = nca.Filename; log?.WriteLine("Found Biggest NCA {0}", nca.Filename); processBiggestNca(nca, ref title); } if (nca.Header.ContentType == ContentType.Data) { title.filename = nca.Filename; log?.WriteLine("Found Biggest NCA {0}", nca.Filename); processBiggestNca(nca, ref title); } else if (nca.Header.ContentType == ContentType.Meta) { processCnmtNca(nca, ref title, false); } else if (nca.Header.ContentType == ContentType.Control) { log?.WriteLine("Found Control NCA {0}", nca.Filename); processControlNca(nca, ref title); } else if (nca.Header.ContentType == ContentType.AocData) { title.filename = nca.Filename; log?.WriteLine("Found Biggest NCA {0}", nca.Filename); processBiggestNca(nca, ref title); } } if (title.type == TitleType.Application || title.type == TitleType.Patch) { if (versionList.TryGetValue(title.baseTitleID, out uint version)) { title.latestVersion = version; } } if (title.type == TitleType.Patch) { title.titleID = title.titleID.Substring(0, Math.Min(title.titleID.Length, 13)) + "800"; } if (title.version > 0) { string titleID = title.type == TitleType.AddOnContent ? title.titleID : title.baseTitleID ?? ""; if (latestVersions.TryGetValue(titleID, out uint version)) { if (title.version > version) { latestVersions[titleID] = title.version; } } else { latestVersions.Add(titleID, title.version); } } log?.WriteLine("Title information for {0}: [{1}] {2}", title.filename, title.titleID, title.titleName); return(title); }
private static (string, string) processCnmtXml(IStorage cnmtXml, ref Title title) { string biggestNca = null, controlNca = null; log?.WriteLine("Processing CNMT XML"); Stream stream = cnmtXml.AsStream(); byte[] buffer = new byte[stream.Length]; stream.Read(buffer, 0, buffer.Length); stream.Close(); byte[] bom = Encoding.UTF8.GetPreamble(); if (buffer.Take(bom.Length).SequenceEqual(bom)) { Array.Copy(buffer, bom.Length, buffer, 0, buffer.Length - bom.Length); Array.Resize(ref buffer, buffer.Length - bom.Length); } XDocument xml = XDocument.Parse(Encoding.UTF8.GetString(buffer).Replace("&", "&")); Enum.TryParse(xml.Element("ContentMeta").Element("Type").Value, true, out TitleType titleType); title.type = titleType; title.titleID = xml.Element("ContentMeta").Element("Id").Value.Remove(1, 2).ToUpper(); title.baseTitleID = String.IsNullOrEmpty(title.titleID) ? "" : title.titleID.Substring(0, Math.Min(title.titleID.Length, 13)) + "000"; title.version = Convert.ToUInt32(xml.Element("ContentMeta").Element("Version").Value); title.systemUpdate = (uint)(Convert.ToUInt64(xml.Element("ContentMeta").Element("RequiredSystemVersion").Value) % 0x100000000); title.masterkey = (uint)Math.Max(Convert.ToInt32(xml.Element("ContentMeta").Element("KeyGenerationMin").Value) - 1, 0); foreach (XElement element in xml.Descendants("Content")) { if (title.type == TitleType.Application || title.type == TitleType.Patch) { if (element.Element("Type").Value == "Program") { biggestNca = element.Element("Id").Value + ".nca"; log?.WriteLine("Found Biggest NCA {0}", biggestNca); } else if (element.Element("Type").Value == "Control") { controlNca = element.Element("Id").Value + ".nca"; log?.WriteLine("Found Control NCA {0}", controlNca); } } else if (title.type == TitleType.AddOnContent) { if (element.Element("Type").Value == "Data") { biggestNca = element.Element("Id").Value + ".nca"; log?.WriteLine("Found Biggest NCA {0}", biggestNca); } } } return(biggestNca, controlNca); }
public static Title processNsp(string filename) { Title title = new Title(); using (var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { Pfs pfs; string biggestNca = null, controlNca = null; try { pfs = new Pfs(filestream.AsStorage()); title.distribution = Title.Distribution.Digital; log?.WriteLine("Processing NSP {0}", filename); PfsFileEntry[] fileEntries = pfs.Files; foreach (PfsFileEntry entry in fileEntries) { if (entry.Name.EndsWith(".cnmt.xml")) { try { using (var cnmtXml = pfs.OpenFile(entry)) { (biggestNca, controlNca) = processCnmtXml(cnmtXml, ref title); } } catch (FileNotFoundException) { } title.structure.Add(Title.Structure.CnmtXml); } else if (entry.Name.EndsWith(".cnmt.nca")) { try { using (var cnmtNca = pfs.OpenFile(entry)) { var nca = processCnmtNca(cnmtNca, ref title); if (nca.Item1 != null && (nca.Item2 != null || title.type == TitleType.AddOnContent)) { (biggestNca, controlNca) = nca; } } } catch (FileNotFoundException) { if (pfs.FileExists(entry.Name.Replace(".nca", ".ncz"))) { title.error = "Unsupported Format: Compressed NCA"; } } title.structure.Add(Title.Structure.CnmtNca); } else if (entry.Name.EndsWith(".cert")) { title.structure.Add(Title.Structure.Cert); } else if (entry.Name.EndsWith(".tik")) { try { using (var tik = pfs.OpenFile(entry)) { if (entry.Name.Split('.')[0].TryToBytes(out byte[] rightsId)) { processTik(tik, rightsId, ref keyset, out byte[] titleKey); title.titleKey = BitConverter.ToString(titleKey).Replace("-", "").ToUpper(); } } } catch (FileNotFoundException) { if (pfs.FileExists(entry.Name.Replace(".nca", ".ncz"))) { title.error = "Unsupported Format: Compressed NCA"; } } title.structure.Add(Title.Structure.Tik); } else if (entry.Name.EndsWith(".legalinfo.xml")) { title.structure.Add(Title.Structure.LegalinfoXml); } else if (entry.Name.EndsWith(".nacp.xml")) { try { using (var nacpXml = pfs.OpenFile(entry)) { processNacpXml(nacpXml, ref title); } } catch (FileNotFoundException) { } title.structure.Add(Title.Structure.NacpXml); } else if (entry.Name.EndsWith(".programinfo.xml")) { title.structure.Add(Title.Structure.PrograminfoXml); } else if (entry.Name.Equals("cardspec.xml")) { title.structure.Add(Title.Structure.CardspecXml); } else if (entry.Name.Equals("authoringtoolinfo.xml")) { title.structure.Add(Title.Structure.AuthoringtoolinfoXml); } } if (!String.IsNullOrEmpty(biggestNca)) { try { using (var biggest = pfs.OpenFile(biggestNca)) { processBiggestNca(biggest, ref title); } } catch (FileNotFoundException) { if (pfs.FileExists(biggestNca.Replace(".nca", ".ncz"))) { title.error = "Unsupported Format: Compressed NCA"; } } } if (!String.IsNullOrEmpty(controlNca)) { try { using (var control = pfs.OpenFile(controlNca)) { processControlNca(control, ref title); } } catch (FileNotFoundException) { if (pfs.FileExists(controlNca.Replace(".nca", ".ncz"))) { title.error = "Unsupported Format: Compressed NCA"; } } } } catch (InvalidDataException) { return(null); } } if (title.type == TitleType.Application || title.type == TitleType.Patch) { if (versionList.TryGetValue(title.baseTitleID, out uint version)) { title.latestVersion = version; } } log?.WriteLine("NSP information for {0}: [{1}] {2}", filename, title.titleID, title.titleName); return(title); }
static void processPaths(List <string> paths, string sort, bool sdcard) { List <Title> titles = new List <Title>(); foreach (string path in paths) { if (Directory.Exists(path)) { if (sdcard) { titles.AddRange(openSDCard(path)); } else { titles.AddRange(openDirectory(path)); } } else if (File.Exists(path) && (Common.Settings.Default.NszExtension ? new string[] { ".xci", ".nsp", ".xcz", ".nsz", ".nro" } : new string[] { ".xci", ".nsp", ".nro" }).Any(ext => ext.Equals(Path.GetExtension(path).ToLower())) && !sdcard) { Title title = openFile(path); if (title != null) { titles.Add(title); } } else { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Error.WriteLine("{0} is not supported or not a valid path", path); Console.ResetColor(); } } titles = titles.Distinct().OrderBy(x => sort.Equals("titleid") ? x.titleID : sort.Equals("titlename") ? x.titleName : x.filename).ToList(); foreach (Title title in titles) { if (title.permission == Title.Permission.Dangerous) { Console.ForegroundColor = ConsoleColor.DarkRed; } else if (title.permission == Title.Permission.Unsafe) { Console.ForegroundColor = ConsoleColor.DarkMagenta; } else { Console.ForegroundColor = ConsoleColor.Green; } Console.WriteLine("\n{0}", title.filename); Console.ResetColor(); Console.WriteLine(@"├ {0}: {1} ├ {2}: {3} ├ {4}: {5} ├ {6}: {7} ├ {8}: {9} ├ {10}: {11} ├ {12}: {13} ├ {14}: {15} ├ {16}: {17} ├ {18}: {19} ├ {20}: {21} ├ {22}: {23} ├ {24}: {25} ├ {26}: {27} ├ {28}: {29} ├ {30}: {31} ├ {32}: {33} ├ {34}: {35} ├ {36}: {37} ├ {38}: {39} └ {40}: {41}", Title.Properties[0], title.titleID, Title.Properties[1], title.baseTitleID, Title.Properties[2], title.titleName, Title.Properties[3], title.displayVersion, Title.Properties[4], title.versionString, Title.Properties[5], title.latestVersionString, Title.Properties[6], title.systemUpdateString, Title.Properties[7], title.systemVersionString, Title.Properties[8], title.applicationVersionString, Title.Properties[9], title.masterkeyString, Title.Properties[10], title.titleKey, Title.Properties[11], title.publisher, Title.Properties[12], title.languagesString, Title.Properties[13], title.filename, Title.Properties[14], title.filesizeString, Title.Properties[15], title.typeString, Title.Properties[16], title.distribution, Title.Properties[17], title.structureString, Title.Properties[18], title.signatureString, Title.Properties[19], title.permissionString, Title.Properties[20], title.error ); } Process.log?.WriteLine("\n{0} titles processed", titles.Count); Console.Error.WriteLine("\n{0} titles processed", titles.Count); }
void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; titles.Clear(); if (e.Argument is List <string> filenames) { int count = filenames.Count, index = 0; foreach (var filename in filenames) { if (worker.CancellationPending) { break; } worker.ReportProgress(100 * index++ / count, filename); Title title = Process.processFile(filename); if (title != null) { titles.Add(title); } } if (!worker.CancellationPending) { worker.ReportProgress(100, ""); } Process.log?.WriteLine("\n{0} titles processed", titles.Count); } else if (e.Argument is string path) { List <FsTitle> fsTitles = Process.processSd(path); if (fsTitles != null) { int count = fsTitles.Count, index = 0; foreach (var fsTitle in fsTitles) { if (worker.CancellationPending) { break; } worker.ReportProgress(100 * index++ / count, fsTitle.MainNca?.Filename); Title title = Process.processTitle(fsTitle); if (title != null) { titles.Add(title); } } if (!worker.CancellationPending) { worker.ReportProgress(100, ""); } Process.log?.WriteLine("\n{0} titles processed", titles.Count); } else { string error = "SD card \"Contents\" directory could not be found"; Process.log?.WriteLine(error); e.Result = error; return; } } e.Result = titles; }
public static Title processXci(string filename) { Title title = new Title(); using (var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { Xci xci; string biggestNca = null, controlNca = null; try { xci = new Xci(keyset, filestream.AsStorage()); title.distribution = Title.Distribution.Cartridge; log?.WriteLine("Processing XCI {0}", filename); if (xci.RootPartition?.Files.Length > 0) { title.structure.Add(Title.Structure.RootPartition); } if (xci.UpdatePartition?.Files.Length > 0) { PfsFileEntry[] fileEntries = xci.UpdatePartition.Files; List <string> cnmtNca = fileEntries.Select(x => x.Name).Where(x => x.EndsWith(".cnmt.nca")).Intersect(Title.SystemUpdate.Keys).ToList(); if (cnmtNca.Any()) { uint systemUpdate = unchecked ((uint)-1); Title.SystemUpdate.TryGetValue(cnmtNca.First(), out systemUpdate); title.systemUpdate = systemUpdate; } title.structure.Add(Title.Structure.UpdatePartition); } if (xci.NormalPartition?.Files.Length > 0) { title.structure.Add(Title.Structure.NormalPartition); } if (xci.SecurePartition?.Files.Length > 0) { PfsFileEntry[] fileEntries = xci.SecurePartition.Files; foreach (PfsFileEntry entry in fileEntries) { if (entry.Name.EndsWith(".cnmt.nca")) { try { using (var cnmtNca = xci.SecurePartition.OpenFile(entry)) { var nca = processCnmtNca(cnmtNca, ref title); if (nca.Item1 != null && (nca.Item2 != null || title.type == TitleType.AddOnContent)) { (biggestNca, controlNca) = nca; } } } catch (FileNotFoundException) { if (xci.SecurePartition.FileExists(entry.Name.Replace(".nca", ".ncz"))) { title.error = "Unsupported Format: Compressed NCA"; } } title.structure.Add(Title.Structure.CnmtNca); } else if (entry.Name.EndsWith(".cert")) { title.structure.Add(Title.Structure.Cert); } else if (entry.Name.EndsWith(".tik")) { try { using (var tik = xci.SecurePartition.OpenFile(entry)) { if (entry.Name.Split('.')[0].TryToBytes(out byte[] rightsId)) { processTik(tik, rightsId, ref keyset, out byte[] titleKey); title.titleKey = BitConverter.ToString(titleKey).Replace("-", "").ToUpper(); } } } catch (FileNotFoundException) { if (xci.SecurePartition.FileExists(entry.Name.Replace(".nca", ".ncz"))) { title.error = "Unsupported Format: Compressed NCA"; } } title.structure.Add(Title.Structure.Tik); } } if (!String.IsNullOrEmpty(biggestNca)) { try { using (var biggest = xci.SecurePartition.OpenFile(biggestNca)) { processBiggestNca(biggest, ref title); } } catch (FileNotFoundException) { if (xci.SecurePartition.FileExists(biggestNca.Replace(".nca", ".ncz"))) { title.error = "Unsupported Format: Compressed NCA"; } } } if (!String.IsNullOrEmpty(controlNca)) { try { using (var control = xci.SecurePartition.OpenFile(controlNca)) { processControlNca(control, ref title); } } catch (FileNotFoundException) { if (xci.SecurePartition.FileExists(controlNca.Replace(".nca", ".ncz"))) { title.error = "Unsupported Format: Compressed NCA"; } } } title.structure.Add(Title.Structure.SecurePartition); } if (xci.LogoPartition?.Files.Length > 0) { title.structure.Add(Title.Structure.LogoPartition); } } catch (InvalidDataException) { return(null); } } if (title.type == TitleType.Application || title.type == TitleType.Patch) { if (versionList.TryGetValue(title.baseTitleID, out uint version)) { title.latestVersion = version; } } log?.WriteLine("XCI information for {0}: [{1}] {2}", filename, title.titleID, title.titleName); return(title); }
public override NSView GetViewForItem(NSTableView tableView, NSTableColumn tableColumn, nint row) { NSTextField textField = (NSTextField)tableView.MakeView("TextField", null); if (textField == null) { textField = new NSTextField { BackgroundColor = NSColor.Clear, Bordered = false, Editable = false, }; } Title title = dataSource.Titles[(int)row]; switch (tableColumn.Identifier) { case "TitleID": textField.StringValue = title.titleID ?? ""; break; case "TitleName": textField.StringValue = title.titleName ?? ""; break; case "DisplayVersion": textField.StringValue = title.displayVersion ?? ""; break; case "Version": textField.StringValue = title.versionString ?? ""; break; case "LatestVersion": textField.StringValue = title.latestVersionString ?? ""; break; case "Firmware": textField.StringValue = title.firmware ?? ""; break; case "MasterKey": textField.StringValue = title.masterkeyString ?? ""; break; case "FileName": textField.StringValue = title.filename ?? ""; break; case "FileSize": textField.StringValue = NSByteCountFormatter.Format(title.filesize, NSByteCountFormatterCountStyle.File) ?? ""; break; case "Type": textField.StringValue = title.typeString ?? ""; break; case "Distribution": textField.StringValue = title.distribution.ToString() ?? ""; break; case "Structure": textField.StringValue = title.structureString ?? ""; break; case "Signature": textField.StringValue = title.signatureString ?? ""; break; case "Permission": textField.StringValue = title.permissionString ?? ""; break; case "Error": textField.StringValue = title.error ?? ""; break; } if (title.signature != true) { textField.BackgroundColor = NSColor.Gray.ColorWithAlphaComponent((nfloat)0.1); } if (title.permission == Title.Permission.Dangerous) { textField.TextColor = NSColor.Red; } else if (title.permission == Title.Permission.Unsafe) { textField.TextColor = NSColor.Purple; } textField.Cell.LineBreakMode = NSLineBreakMode.CharWrapping; return(textField); }
public static Title processXci(string filename) { Title title = new Title(); using (var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { Xci xci; string biggestNca = null, controlNca = null; try { xci = new Xci(keyset, filestream.AsStorage()); title.distribution = Title.Distribution.Cartridge; } catch (InvalidDataException) { return(null); } log?.WriteLine("Processing XCI {0}", filename); if (xci.RootPartition?.Files.Length > 0) { title.structure.Add(Title.Structure.RootPartition); } if (xci.UpdatePartition?.Files.Length > 0) { title.structure.Add(Title.Structure.UpdatePartition); } if (xci.NormalPartition?.Files.Length > 0) { title.structure.Add(Title.Structure.NormalPartition); } if (xci.SecurePartition?.Files.Length > 0) { PfsFileEntry[] fileEntries = xci.SecurePartition.Files; foreach (PfsFileEntry entry in fileEntries) { if (entry.Name.EndsWith(".cnmt.nca")) { using (var cnmtNca = xci.SecurePartition.OpenFile(entry)) { var nca = processCnmtNca(cnmtNca, ref title); if (nca.Item1 != null && (nca.Item2 != null || title.type == TitleType.AddOnContent)) { (biggestNca, controlNca) = nca; } } title.structure.Add(Title.Structure.CnmtNca); } } if (!String.IsNullOrEmpty(biggestNca)) { using (var biggest = xci.SecurePartition.OpenFile(biggestNca)) { processBiggestNca(biggest, ref title); } } if (!String.IsNullOrEmpty(controlNca)) { using (var control = xci.SecurePartition.OpenFile(controlNca)) { processControlNca(control, ref title); } } title.structure.Add(Title.Structure.SecurePartition); } if (xci.LogoPartition?.Files.Length > 0) { title.structure.Add(Title.Structure.LogoPartition); } } if (title.type == TitleType.Application || title.type == TitleType.Patch) { if (versionList.TryGetValue(title.titleIDApplication, out uint version)) { title.latestVersion = version; } } log?.WriteLine("XCI information for {0}: [{1}] {2}", filename, title.titleID, title.titleName); return(title); }
private static void processControlNca(IStorage controlNca, ref Title title) { Nca nca = new Nca(keyset, controlNca, false); processControlNca(nca, ref title); }
public static Title processNsp(string filename) { Title title = new Title(); using (var filestream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { Pfs pfs; string biggestNca = null, controlNca = null; try { pfs = new Pfs(filestream.AsStorage()); title.distribution = Title.Distribution.Digital; } catch (InvalidDataException) { return(null); } log?.WriteLine("Processing NSP {0}", filename); PfsFileEntry[] fileEntries = pfs.Files; foreach (PfsFileEntry entry in fileEntries) { if (entry.Name.EndsWith(".cnmt.xml")) { using (var cnmtXml = pfs.OpenFile(entry)) { (biggestNca, controlNca) = processCnmtXml(cnmtXml, ref title); } title.structure.Add(Title.Structure.CnmtXml); } else if (entry.Name.EndsWith(".cnmt.nca")) { using (var cnmtNca = pfs.OpenFile(entry)) { var nca = processCnmtNca(cnmtNca, ref title); if (nca.Item1 != null && (nca.Item2 != null || title.type == TitleType.AddOnContent)) { (biggestNca, controlNca) = nca; } } title.structure.Add(Title.Structure.CnmtNca); } else if (entry.Name.EndsWith(".cert")) { title.structure.Add(Title.Structure.Cert); } else if (entry.Name.EndsWith(".tik")) { title.structure.Add(Title.Structure.Tik); } else if (entry.Name.EndsWith(".legalinfo.xml")) { title.structure.Add(Title.Structure.LegalinfoXml); } else if (entry.Name.EndsWith(".nacp.xml")) { using (var nacpXml = pfs.OpenFile(entry)) { processNacpXml(nacpXml, ref title); } title.structure.Add(Title.Structure.NacpXml); } else if (entry.Name.EndsWith(".programinfo.xml")) { title.structure.Add(Title.Structure.PrograminfoXml); } else if (entry.Name.Equals("cardspec.xml")) { title.structure.Add(Title.Structure.CardspecXml); } else if (entry.Name.Equals("authoringtoolinfo.xml")) { title.structure.Add(Title.Structure.AuthoringtoolinfoXml); } } if (!String.IsNullOrEmpty(biggestNca)) { using (var biggest = pfs.OpenFile(biggestNca)) { processBiggestNca(biggest, ref title); } } if (!String.IsNullOrEmpty(controlNca)) { using (var control = pfs.OpenFile(controlNca)) { processControlNca(control, ref title); } } } if (title.type == TitleType.Application || title.type == TitleType.Patch) { if (versionList.TryGetValue(title.titleIDApplication, out uint version)) { title.latestVersion = version; } } log?.WriteLine("NSP information for {0}: [{1}] {2}", filename, title.titleID, title.titleName); return(title); }
private void backgroundWorkerProcess_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; titles.Clear(); Process.latestVersions.Clear(); if (e.Argument is ValueTuple <Worker, string[]> argumentFile) { if (argumentFile.Item1 == Worker.File && argumentFile.Item2 is string[] files) { List <string> filenames = files.ToList(); filenames.Sort(); Process.log?.WriteLine("{0} files selected", filenames.Count); worker.ReportProgress(-1, String.Format("Opening {0} files", filenames.Count)); int count = filenames.Count, index = 0; foreach (var filename in filenames) { if (worker.CancellationPending) { break; } worker.ReportProgress(100 * index++ / count, filename); Title title = Process.processFile(filename); if (title != null) { titles.Add(title); } } if (!worker.CancellationPending) { worker.ReportProgress(100, ""); } Process.log?.WriteLine("\n{0} titles processed", titles.Count); } } else if (e.Argument is ValueTuple <Worker, string> argumentPath) { if (argumentPath.Item1 == Worker.Directory && argumentPath.Item2 is string path) { List <string> filenames = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories) .Where(filename => filename.ToLower().EndsWith(".xci") || filename.ToLower().EndsWith(".nsp") || filename.ToLower().EndsWith(".nro") || (Common.Settings.Default.NszExtension && (filename.ToLower().EndsWith(".xcz") || filename.ToLower().EndsWith(".nsz")))).ToList(); filenames.Sort(); Process.log?.WriteLine("{0} files selected", filenames.Count); worker.ReportProgress(-1, String.Format("Opening {0} files from directory {1}", filenames.Count, path)); int count = filenames.Count, index = 0; foreach (var filename in filenames) { if (worker.CancellationPending) { break; } worker.ReportProgress(100 * index++ / count, filename); Title title = Process.processFile(filename); if (title != null) { titles.Add(title); } } if (!worker.CancellationPending) { worker.ReportProgress(100, ""); } Process.log?.WriteLine("\n{0} titles processed", titles.Count); } else if (argumentPath.Item1 == Worker.SDCard && argumentPath.Item2 is string pathSd) { List <FsTitle> fsTitles = Process.processSd(pathSd); if (fsTitles != null) { int count = fsTitles.Count, index = 0; foreach (var fsTitle in fsTitles) { if (worker.CancellationPending) { break; } worker.ReportProgress(100 * index++ / count, fsTitle.MainNca?.Filename); Title title = Process.processTitle(fsTitle); if (title != null) { titles.Add(title); } } if (!worker.CancellationPending) { worker.ReportProgress(100, ""); } Process.log?.WriteLine("\n{0} titles processed", titles.Count); } else { worker.ReportProgress(0, ""); string error = "SD card \"Contents\" directory could not be found"; Process.log?.WriteLine(error); e.Result = error; return; } } } e.Result = titles; }