public void ExtractFiles(string tableOfContentsName) { string superBundlePath = Path.ChangeExtension(tableOfContentsName, "sb"); string directory = Path.GetDirectoryName(tableOfContentsName) + @"\" + Path.GetFileNameWithoutExtension(tableOfContentsName); // extract raw files from superbundles if (!myTableOfContents.Payload.Properties.ContainsKey("cas")) { foreach (var collection in myTableOfContents.Payload.BundleCollections) { string collectionDirectory = directory + @"\" + collection.Name + @"\"; foreach (var item in collection.Bundles) { if (item.Properties.ContainsKey("offset") && item.Properties.ContainsKey("size")) { Directory.CreateDirectory(collectionDirectory); using (FileStream inputFileStream = File.Open(superBundlePath, FileMode.Open)) { BinaryReader reader = new BinaryReader(inputFileStream); long a = (long)item.Properties["offset"].Value; reader.BaseStream.Seek((int)a, SeekOrigin.Begin); string finalName = collectionDirectory + Helpers.ByteArrayToString((byte[])item.Properties["id"].Value); ChunkHandler.Dechunk(finalName, reader, (int)item.Properties["size"].Value); } } } } } // extract from a catalogue else { foreach (CatalogueEntry entry in BuildFileListInCatalogues(myTableOfContents.Payload.BundleCollections)) { string compoundName = Path.GetDirectoryName(entry.Parent.Path) + @"\cas_" + entry.Archive.ToString("00") + ".cas"; using (FileStream inputFileStream = File.Open(compoundName, FileMode.Open)) { BinaryReader reader = new BinaryReader(inputFileStream); reader.BaseStream.Seek(entry.Offset, SeekOrigin.Begin); string finalName = directory + @"\" + entry.ResolvedName.Replace(":", "_Dq_"); Directory.CreateDirectory(finalName.Substring(0, finalName.LastIndexOf('\\'))); ChunkHandler.Dechunk(finalName, reader, entry.Size); } } } }
public void ImportFiles(string tableOfContentsName) { Dictionary <string, string> filesToOverwriteMap = new Dictionary <string, string>(); string directory = Path.GetDirectoryName(tableOfContentsName) + @"\" + Path.GetFileNameWithoutExtension(tableOfContentsName); Random generator = new Random(); ResolveNewFiles(tableOfContentsName, directory); bool isIndirect = myTableOfContents.Payload.BundleCollections.Where(bundleList => bundleList.Bundles.Count() > 0).First().Bundles.First().Indirection != null; List <bool> isIndirectionConsistentAndMatching = myTableOfContents.Payload.BundleCollections.Select(bundleList => bundleList.Bundles.All(bundle => (bundle.Indirection != null) == isIndirect)).Distinct().ToList(); bool isIndirectOrMixed = false; if (isIndirectionConsistentAndMatching.Count() != 1 || !isIndirectionConsistentAndMatching.First()) { isIndirectOrMixed = true; } string originalSuperBundlePath = Path.ChangeExtension(tableOfContentsName, "sb"); string newSuperBundlePath = Path.ChangeExtension(tableOfContentsName, "sb_" + generator.Next().ToString()); // table of contents pointing directly to raw files in superbundles if (!myTableOfContents.Payload.Properties.ContainsKey("cas")) { filesToOverwriteMap.Add(originalSuperBundlePath, newSuperBundlePath); // write superbundle var allBundles = myTableOfContents.Payload.BundleCollections.SelectMany(bundleList => bundleList.Bundles).OrderBy(superBundle => (long)superBundle.Properties["offset"].Value); using (BinaryReader originalReader = new BinaryReader(File.Open(originalSuperBundlePath, FileMode.Open))) { using (BundleBinaryWriter writer = new BundleBinaryWriter(File.Open(newSuperBundlePath, FileMode.Create))) { foreach (SuperBundle superBundle in allBundles) { Int64 initialFilePosition = writer.BaseStream.Position; if (superBundle.Changed == null) { long offset = (long)superBundle.Properties["offset"].Value; originalReader.BaseStream.Seek(offset, SeekOrigin.Begin); writer.Write(originalReader.ReadBytes((int)superBundle.Properties["size"].Value)); } else { superBundle.Properties["size"].Value = ChunkHandler.Chunk(writer, superBundle); } superBundle.Properties["offset"].Value = initialFilePosition; } } } // write table of contents string newTableOfContentsName = Path.ChangeExtension(tableOfContentsName, @".toc_" + generator.Next().ToString()); filesToOverwriteMap.Add(tableOfContentsName, newTableOfContentsName); using (BundleBinaryWriter writer = new BundleBinaryWriter(File.Open(newTableOfContentsName, FileMode.Create))) { writer.Write(myTableOfContents.Header); writer.Write(myTableOfContents.Payload); } } // table of contents pointing to raw files in catalogues else { IEnumerable <SuperBundle> modifiedBundles; if (isIndirectOrMixed) { modifiedBundles = myTableOfContents.Payload.BundleCollections .SelectMany(bundleList => bundleList.Bundles .Where(superBundles => superBundles.Indirection != null) .SelectMany(superBundles => superBundles.Indirection.BundleCollections .SelectMany(indirectBundleList => indirectBundleList.Bundles))) .Where(bundle => bundle.Changed != null); } else { modifiedBundles = myTableOfContents.Payload.BundleCollections.SelectMany(bundleList => bundleList.Bundles).Where(bundle => bundle.Changed != null); } // write cas foreach (SuperBundle superBundle in modifiedBundles) { CatalogueEntry catEntry = FindCorrespondingCatalogueEntry((byte[])superBundle.Properties["sha1"].Value); catEntry.Changed = true; string pathToNewCascade = Path.GetDirectoryName(catEntry.Parent.Path) + @"\\" + "cas_99.cas"; catEntry.Archive = 99; using (BundleBinaryWriter writer = new BundleBinaryWriter(File.Open(pathToNewCascade, FileMode.Append))) { if (writer.BaseStream.Position == 0 && myTableOfContents.Header.Version == 0x03) { writer.Write(Catalogue.CasHeader); } catEntry.Offset = (int)writer.BaseStream.Position; int fileSize = ChunkHandler.Chunk(writer, superBundle); catEntry.Size = fileSize; if (superBundle.Properties.ContainsKey("size")) { superBundle.Properties["size"].Value = (Int64)fileSize; } if (superBundle.Properties.ContainsKey("originalSize")) { superBundle.Properties["originalSize"].Value = (Int64) new FileInfo(superBundle.Changed).Length; } } } // write catalogue foreach (Catalogue catalogue in myCatalogues.Where(_ => _.Files.Values.Any(entry => entry.Changed))) { // fix for duplicates catalogue.NumberOfFiles = catalogue.Files.Count; string newCataloguePath = catalogue.Path + "_tmp" + generator.Next().ToString(); filesToOverwriteMap.Add(catalogue.Path, newCataloguePath); using (BundleBinaryWriter writer = new BundleBinaryWriter(File.Open(newCataloguePath, FileMode.Create))) { writer.Write(myTableOfContents.Header.Version, catalogue); } } // write superbundle if (isIndirectOrMixed) { filesToOverwriteMap.Add(originalSuperBundlePath, newSuperBundlePath); // write table of contents using (BundleBinaryWriter writer = new BundleBinaryWriter(File.Open(newSuperBundlePath, FileMode.Create))) { using (BinaryReader originalReader = new BinaryReader(File.Open(originalSuperBundlePath, FileMode.Open))) { originalReader.BaseStream.Seek(0, SeekOrigin.Begin); writer.Write(originalReader.ReadBytes(16)); } foreach (SuperBundle indirectSuperBundle in myTableOfContents.Payload.BundleCollections.SelectMany(_ => _.Bundles.Select(x => x.Indirection))) { writer.Write(indirectSuperBundle); } writer.Write((Int16)0); } } } CleanupTemporaryFiles(filesToOverwriteMap); }