public static ProgramInfoXml GetProgramInfoXml(List <NintendoSubmissionPackageFileSystemInfo.ContentInfo> contentInfos, KeyConfiguration config)
        {
            NintendoSubmissionPackageFileSystemInfo.ContentInfo contentInfo = contentInfos.Where <NintendoSubmissionPackageFileSystemInfo.ContentInfo>((Func <NintendoSubmissionPackageFileSystemInfo.ContentInfo, bool>)(x => x.ContentType == "Program")).ToList <NintendoSubmissionPackageFileSystemInfo.ContentInfo>().Single <NintendoSubmissionPackageFileSystemInfo.ContentInfo>();
            string fileName = "main";
            string filePath = "";

            byte[] data = (byte[])null;
            bool   flag = false;

            if (contentInfo.FsInfo != null)
            {
                NintendoContentFileSystemInfo.EntryInfo entryInfo = (contentInfo.FsInfo as NintendoContentFileSystemInfo).fsEntries.Where <NintendoContentFileSystemInfo.EntryInfo>((Func <NintendoContentFileSystemInfo.EntryInfo, bool>)(x => x.partitionIndex == 0)).Single <NintendoContentFileSystemInfo.EntryInfo>();
                PartitionFileSystemInfo fileSystemInfo            = (PartitionFileSystemInfo)entryInfo.fileSystemInfo;
                if (fileSystemInfo != null && fileSystemInfo.entries.Where <PartitionFileSystemInfo.EntryInfo>((Func <PartitionFileSystemInfo.EntryInfo, bool>)(x => x.name == fileName)).Count <PartitionFileSystemInfo.EntryInfo>() == 1)
                {
                    flag     = true;
                    filePath = fileSystemInfo.entries.Where <PartitionFileSystemInfo.EntryInfo>((Func <PartitionFileSystemInfo.EntryInfo, bool>)(x => x.name == fileName)).Single <PartitionFileSystemInfo.EntryInfo>().path;
                    using (SourceBasedStream sourceBasedStream = new SourceBasedStream(NintendoContentArchiveSource.GetDataSource(entryInfo)))
                    {
                        IFileSystemArchiveReader systemArchiveReader = NintendoSubmissionPackageArchiveUtils.OpenFsReader(entryInfo, (Stream)sourceBasedStream);
                        data = systemArchiveReader.ReadFile(fileName, 0L, systemArchiveReader.GetFileSize(fileName));
                    }
                }
            }
            else
            {
                if (contentInfo.Source == null)
                {
                    throw new NotImplementedException();
                }
                byte[][] areaEncryptionKeys = config.GetKeyAreaEncryptionKeys();
                using (SourceBasedStream sourceBasedStream = new SourceBasedStream(contentInfo.Source))
                {
                    IFileSystemArchiveReader systemArchiveReader = new NintendoContentArchiveReader((Stream)sourceBasedStream, areaEncryptionKeys).OpenFileSystemArchiveReader(0);
                    if (systemArchiveReader.ListFileInfo().Where <Tuple <string, long> >((Func <Tuple <string, long>, bool>)(x => x.Item1 == fileName)).Count <Tuple <string, long> >() == 1)
                    {
                        flag     = true;
                        filePath = systemArchiveReader.ListFileInfo().Where <Tuple <string, long> >((Func <Tuple <string, long>, bool>)(x => x.Item1 == fileName)).Single <Tuple <string, long> >().Item1;
                        data     = systemArchiveReader.ReadFile(fileName, 0L, systemArchiveReader.GetFileSize(fileName));
                    }
                }
            }
            if (!flag)
            {
                Log.Warning("\"main\" was not found in code region.");
                data = new byte[0];
            }
            return(new ProgramInfoXml(new SymbolExtract(data, filePath)));
        }
        public static ApplicationControlPropertyModel GetApplicationControlProperty(List <NintendoSubmissionPackageFileSystemInfo.ContentInfo> contentInfos, KeyConfiguration config)
        {
            List <NintendoSubmissionPackageFileSystemInfo.ContentInfo> list = contentInfos.Where <NintendoSubmissionPackageFileSystemInfo.ContentInfo>((Func <NintendoSubmissionPackageFileSystemInfo.ContentInfo, bool>)(x => x.ContentType == "Control")).ToList <NintendoSubmissionPackageFileSystemInfo.ContentInfo>();

            if (list.Count > 1)
            {
                throw new NotImplementedException("Multiple control contents in an Application are not supported.");
            }
            NintendoSubmissionPackageFileSystemInfo.ContentInfo contentInfo = list.Single <NintendoSubmissionPackageFileSystemInfo.ContentInfo>();
            string fileName = "control.nacp";

            byte[] bytes;
            if (contentInfo.FsInfo != null)
            {
                NintendoContentFileSystemInfo.EntryInfo entryInfo = (contentInfo.FsInfo as NintendoContentFileSystemInfo).fsEntries.Single <NintendoContentFileSystemInfo.EntryInfo>();
                using (SourceBasedStream sourceBasedStream = new SourceBasedStream(NintendoContentArchiveSource.GetDataSource(entryInfo)))
                {
                    IFileSystemArchiveReader systemArchiveReader = NintendoSubmissionPackageArchiveUtils.OpenFsReader(entryInfo, (Stream)sourceBasedStream);
                    bytes = systemArchiveReader.ReadFile(fileName, 0L, systemArchiveReader.GetFileSize(fileName));
                }
            }
            else
            {
                if (contentInfo.Source == null)
                {
                    throw new NotImplementedException();
                }
                byte[][] areaEncryptionKeys = config.GetKeyAreaEncryptionKeys();
                using (SourceBasedStream sourceBasedStream = new SourceBasedStream(contentInfo.Source))
                {
                    IFileSystemArchiveReader systemArchiveReader = new NintendoContentArchiveReader((Stream)sourceBasedStream, areaEncryptionKeys).OpenFileSystemArchiveReader(0);
                    bytes = systemArchiveReader.ReadFile(fileName, 0L, systemArchiveReader.GetFileSize(fileName));
                }
            }
            return(ApplicationControlPropertyModel.PropertyBytesToModel(bytes));
        }
        internal static NintendoSubmissionPackageFileSystemInfo GetProdNspInfo(NintendoSubmissionPackageReader nspReader, KeyConfiguration keyConfig)
        {
            ArchiveReconstructionUtils.GetContentInfoDelegate getContentInfoImpl = (ArchiveReconstructionUtils.GetContentInfoDelegate)(contentInfo => new NintendoSubmissionPackageFileSystemInfo.ContentInfo()
            {
                FsInfo      = (Nintendo.Authoring.FileSystemMetaLibrary.FileSystemInfo)ArchiveReconstructionUtils.GetProdNcaInfo(nspReader.OpenNintendoContentArchiveReader(contentInfo.Id + ".nca", keyConfig.GetKeyAreaEncryptionKeys())),
                ContentType = contentInfo.Type
            });
            ArchiveReconstructionUtils.GetContentMetaInfoDelegate getContentMetaInfoImpl = (ArchiveReconstructionUtils.GetContentMetaInfoDelegate)((ref NintendoSubmissionPackageFileSystemInfo.EntryInfo entry, string contentMetaFileName, ContentMetaModel model) => ArchiveReconstructionUtils.GetCommonContentMetaInfo(ref entry, contentMetaFileName, model, nspReader, keyConfig));
            NintendoSubmissionPackageFileSystemInfo nspInfo = ArchiveReconstructionUtils.GetNspInfo(nspReader, keyConfig, getContentInfoImpl, getContentMetaInfoImpl);

            nspInfo.IsProdEncryption = true;
            return(nspInfo);
        }
        internal static NintendoSubmissionPackageFileSystemInfo GetReplacedNspInfo(NintendoSubmissionPackageReader nspReader, ISource inSource, string targetEntryPath, string descFilePath, KeyConfiguration keyConfig)
        {
            bool isReplaced = false;

            ArchiveReconstructionUtils.GetContentInfoDelegate getContentInfoImpl = (ArchiveReconstructionUtils.GetContentInfoDelegate)(contentInfo =>
            {
                NintendoSubmissionPackageFileSystemInfo.ContentInfo contentInfo1 = new NintendoSubmissionPackageFileSystemInfo.ContentInfo();
                string fileName = contentInfo.Id + ".nca";
                NintendoContentArchiveReader ncaReader = nspReader.OpenNintendoContentArchiveReader(fileName, keyConfig.GetKeyAreaEncryptionKeys());
                if (targetEntryPath.StartsWith(fileName))
                {
                    contentInfo1.FsInfo = (Nintendo.Authoring.FileSystemMetaLibrary.FileSystemInfo)ArchiveReconstructionUtils.GetReplacedNcaInfo(ncaReader, descFilePath, new EntryReplaceRule()
                    {
                        Source = inSource,
                        Path   = targetEntryPath.Substring(fileName.Length + 1)
                    });
                    isReplaced = true;
                }
                else
                {
                    contentInfo1.Source = (ISource) new FileSystemArchvieFileSource((IFileSystemArchiveReader)nspReader, fileName);
                }
                contentInfo1.ContentType = contentInfo.Type;
                return(contentInfo1);
            });
            ArchiveReconstructionUtils.GetContentMetaInfoDelegate getContentMetaInfoImpl = (ArchiveReconstructionUtils.GetContentMetaInfoDelegate)((ref NintendoSubmissionPackageFileSystemInfo.EntryInfo entry, string contentMetaFileName, ContentMetaModel model) =>
            {
                ArchiveReconstructionUtils.GetCommonContentMetaInfo(ref entry, contentMetaFileName, model, nspReader, keyConfig);
                if (!targetEntryPath.StartsWith(contentMetaFileName) || !targetEntryPath.EndsWith(".cnmt"))
                {
                    return;
                }
                NintendoContentMetaReader contentMetaReader1 = new NintendoContentMetaReader(entry.ContentMetaInfo.Data);
                ulong id1     = contentMetaReader1.GetId();
                uint version1 = contentMetaReader1.GetVersion();
                if (inSource.Size != (long)entry.ContentMetaInfo.Data.Length)
                {
                    throw new Exception(".cnmt file specified to be replaced is invalid.");
                }
                ByteData byteData          = inSource.PullData(0L, (int)inSource.Size);
                ArraySegment <byte> buffer = byteData.Buffer;
                byte[] array = buffer.Array;
                buffer = byteData.Buffer;
                int offset    = buffer.Offset;
                byte[] data   = entry.ContentMetaInfo.Data;
                int dstOffset = 0;
                int count     = byteData.Buffer.Count;
                Buffer.BlockCopy((Array)array, offset, (Array)data, dstOffset, count);
                NintendoContentMetaReader contentMetaReader2 = new NintendoContentMetaReader(entry.ContentMetaInfo.Data);
                ulong id2 = contentMetaReader2.GetId();
                if ((long)id1 != (long)id2)
                {
                    throw new ArgumentException(string.Format("Ids of content meta are different. (oldId = {0:x16}, newID = {0:x16})", (object)id1, (object)id2));
                }
                uint version2 = contentMetaReader2.GetVersion();
                Log.Info(string.Format("content meta (ID = {0:x16}) will be replaced : version {1} -> {2}", (object)id1, (object)version1, (object)version2));
                isReplaced = true;
            });
            NintendoSubmissionPackageFileSystemInfo nspInfo = ArchiveReconstructionUtils.GetNspInfo(nspReader, keyConfig, getContentInfoImpl, getContentMetaInfoImpl);

            if (isReplaced)
            {
                return(nspInfo);
            }
            throw new Exception("nothing was replaced.");
        }
        private static void GetCommonContentMetaInfo(ref NintendoSubmissionPackageFileSystemInfo.EntryInfo entry, string contentMetaFileName, ContentMetaModel model, NintendoSubmissionPackageReader nspReader, KeyConfiguration keyConfig)
        {
            IFileSystemArchiveReader systemArchiveReader = nspReader.OpenNintendoContentArchiveReader(contentMetaFileName, keyConfig.GetKeyAreaEncryptionKeys()).OpenFileSystemArchiveReader(0);
            Tuple <string, long>     tuple = systemArchiveReader.ListFileInfo().Single <Tuple <string, long> >();

            entry.ContentMetaInfo = new NintendoSubmissionPackageFileSystemInfo.ContentMetaInfo(systemArchiveReader.ReadFile(tuple.Item1, 0L, tuple.Item2), model);
            NintendoContentMetaReader contentMetaReader = new NintendoContentMetaReader(entry.ContentMetaInfo.Data);

            entry.MetaType = contentMetaReader.GetType();
        }