diff --git a/SabreTools.Helper/Tools/ArchiveTools.cs b/SabreTools.Helper/Tools/ArchiveTools.cs index bba9a7f9..dbdd6fc0 100644 --- a/SabreTools.Helper/Tools/ArchiveTools.cs +++ b/SabreTools.Helper/Tools/ArchiveTools.cs @@ -14,6 +14,7 @@ using Alphaleonis.Win32.Filesystem; using Ionic.Zlib; using ROMVault2.SupportedFiles.Zip; using SharpCompress.Archives; +using SharpCompress.Archives.Rar; using SharpCompress.Archives.SevenZip; using SharpCompress.Archives.Tar; using SharpCompress.Common; @@ -37,28 +38,6 @@ namespace SabreTools.Helper.Tools { private const int _bufferSize = 4096 * 128; - #region Archive-to-Archive Handling - - /// - /// Attempt to copy a file between archives - /// - /// Source archive name - /// Destination archive name - /// Input entry name - /// Output entry name - /// Logger object for file and console output - /// True if the copy was a success, false otherwise - public static bool CopyFileBetweenArchives(string inputArchive, string outDir, string sourceEntryName, Rom destEntry, Logger logger) - { - string temp = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - string realName = ExtractItem(inputArchive, sourceEntryName, temp, logger); - bool success = WriteTorrentZip(realName, outDir, destEntry, logger); - Directory.Delete(temp, true); - return success; - } - - #endregion - #region Extraction /// @@ -84,6 +63,7 @@ namespace SabreTools.Helper.Tools try { + // 7-zip if (at == ArchiveType.SevenZip && (archiveScanLevel & ArchiveScanLevel.SevenZipInternal) != 0) { logger.Verbose("Found archive of type: " + at); @@ -93,14 +73,15 @@ namespace SabreTools.Helper.Tools // Extract all files to the temp directory SevenZipArchive sza = SevenZipArchive.Open(File.OpenRead(input)); - foreach (IArchiveEntry iae in sza.Entries) + foreach (SevenZipArchiveEntry entry in sza.Entries) { - iae.WriteToDirectory(tempDir, new ExtractionOptions{ PreserveFileTime = true, ExtractFullPath = true, Overwrite = true }); + entry.WriteToDirectory(tempDir, new ExtractionOptions{ PreserveFileTime = true, ExtractFullPath = true, Overwrite = true }); } encounteredErrors = false; sza.Dispose(); - } + + // GZip else if (at == ArchiveType.GZip && (archiveScanLevel & ArchiveScanLevel.GZipInternal) != 0) { logger.Verbose("Found archive of type: " + at); @@ -119,6 +100,44 @@ namespace SabreTools.Helper.Tools encounteredErrors = false; } + + // RAR + else if (at == ArchiveType.Rar && (archiveScanLevel & ArchiveScanLevel.RarInternal) != 0) + { + logger.Verbose("Found archive of type: " + at); + + // Create the temp directory + Directory.CreateDirectory(tempDir); + + // Extract all files to the temp directory + RarArchive ra = RarArchive.Open(input); + foreach (RarArchiveEntry entry in ra.Entries) + { + entry.WriteToDirectory(tempDir, new ExtractionOptions { PreserveFileTime = true, ExtractFullPath = true, Overwrite = true }); + } + encounteredErrors = false; + ra.Dispose(); + } + + // TAR + else if (at == ArchiveType.Tar && (archiveScanLevel & ArchiveScanLevel.TarInternal) != 0) + { + logger.Verbose("Found archive of type: " + at); + + // Create the temp directory + Directory.CreateDirectory(tempDir); + + // Extract all files to the temp directory + TarArchive ta = TarArchive.Open(input); + foreach (TarArchiveEntry entry in ta.Entries) + { + entry.WriteToDirectory(tempDir, new ExtractionOptions { PreserveFileTime = true, ExtractFullPath = true, Overwrite = true }); + } + encounteredErrors = false; + ta.Dispose(); + } + + // Zip else if (at == ArchiveType.Zip && (archiveScanLevel & ArchiveScanLevel.ZipInternal) != 0) { logger.Verbose("Found archive of type: " + at); @@ -173,24 +192,6 @@ namespace SabreTools.Helper.Tools } encounteredErrors = false; } - else if (at == ArchiveType.Rar && (archiveScanLevel & ArchiveScanLevel.RarInternal) != 0) - { - logger.Verbose("Found archive of type: " + at); - - // Create the temp directory - Directory.CreateDirectory(tempDir); - - // Extract all files to the temp directory - IReader reader = ReaderFactory.Open(File.OpenRead(input)); - bool succeeded = reader.MoveToNextEntry(); - while (succeeded) - { - reader.WriteEntryToDirectory(tempDir, new ExtractionOptions { PreserveFileTime = true, ExtractFullPath = true, Overwrite = true }); - succeeded = reader.MoveToNextEntry(); - } - encounteredErrors = false; - reader.Dispose(); - } } catch (EndOfStreamException) { @@ -270,67 +271,100 @@ namespace SabreTools.Helper.Tools return st; } - IReader reader = null; try { - if (at == ArchiveType.Zip) + switch (at) { - ZipFile zf = new ZipFile(); - ZipReturn zr = zf.Open(input, new FileInfo(input).LastWriteTime.Ticks, true); - if (zr != ZipReturn.ZipGood) - { - throw new Exception(ZipFile.ZipErrorMessageText(zr)); - } - - for (int i = 0; i < zf.EntriesCount && zr == ZipReturn.ZipGood; i++) - { - logger.Verbose("Current entry name: '" + zf.Entries[i].FileName + "'"); - if (zf.Entries[i].FileName.Contains(entryName)) + case ArchiveType.SevenZip: + SevenZipArchive sza = SevenZipArchive.Open(input, new ReaderOptions { LeaveStreamOpen = false, }); + foreach (SevenZipArchiveEntry entry in sza.Entries) { - realEntry = zf.Entries[i].FileName; - - // Set defaults before writing out - Stream readStream; - ulong streamsize = 0; - CompressionMethod cm = CompressionMethod.Stored; - uint lastMod = 0; - - zr = zf.OpenReadStream(i, false, out readStream, out streamsize, out cm, out lastMod); - - byte[] ibuffer = new byte[_bufferSize]; - int ilen; - while ((ilen = readStream.Read(ibuffer, 0, _bufferSize)) > 0) + logger.Verbose("Current entry name: '" + entry.Key + "'"); + if (entry != null && !entry.IsDirectory && entry.Key.Contains(entryName)) { - st.Write(ibuffer, 0, ilen); - st.Flush(); + realEntry = entry.Key; + entry.WriteTo(st); + break; } - - zr = zf.CloseReadStream(); } - } - } - else if (at == ArchiveType.SevenZip || at == ArchiveType.Rar) - { - reader = ReaderFactory.Open(File.OpenRead(input)); - while (reader.MoveToNextEntry()) - { - logger.Verbose("Current entry name: '" + reader.Entry.Key + "'"); - if (reader.Entry != null && reader.Entry.Key.Contains(entryName)) + sza.Dispose(); + break; + + case ArchiveType.GZip: + // Decompress the input stream + realEntry = Path.GetFileNameWithoutExtension(input); + GZipStream gzstream = new GZipStream(File.OpenRead(input), CompressionMode.Decompress); + gzstream.CopyTo(st); + + // Dispose of the stream + gzstream.Dispose(); + break; + + case ArchiveType.Rar: + RarArchive ra = RarArchive.Open(input, new ReaderOptions { LeaveStreamOpen = false, }); + foreach (RarArchiveEntry entry in ra.Entries) { - realEntry = reader.Entry.Key; - reader.WriteEntryTo(st); + logger.Verbose("Current entry name: '" + entry.Key + "'"); + if (entry != null && !entry.IsDirectory && entry.Key.Contains(entryName)) + { + realEntry = entry.Key; + entry.WriteTo(st); + break; + } } - } - } - else if (at == ArchiveType.GZip) - { - // Decompress the input stream - realEntry = Path.GetFileNameWithoutExtension(input); - GZipStream gzstream = new GZipStream(File.OpenRead(input), CompressionMode.Decompress); - gzstream.CopyTo(st); + ra.Dispose(); + break; - // Dispose of the stream - gzstream.Dispose(); + case ArchiveType.Tar: + TarArchive ta = TarArchive.Open(input, new ReaderOptions { LeaveStreamOpen = false, }); + foreach (TarArchiveEntry entry in ta.Entries) + { + logger.Verbose("Current entry name: '" + entry.Key + "'"); + if (entry != null && !entry.IsDirectory && entry.Key.Contains(entryName)) + { + realEntry = entry.Key; + entry.WriteTo(st); + break; + } + } + ta.Dispose(); + break; + + case ArchiveType.Zip: + ZipFile zf = new ZipFile(); + ZipReturn zr = zf.Open(input, new FileInfo(input).LastWriteTime.Ticks, true); + if (zr != ZipReturn.ZipGood) + { + throw new Exception(ZipFile.ZipErrorMessageText(zr)); + } + + for (int i = 0; i < zf.EntriesCount && zr == ZipReturn.ZipGood; i++) + { + logger.Verbose("Current entry name: '" + zf.Entries[i].FileName + "'"); + if (zf.Entries[i].FileName.Contains(entryName)) + { + realEntry = zf.Entries[i].FileName; + + // Set defaults before writing out + Stream readStream; + ulong streamsize = 0; + CompressionMethod cm = CompressionMethod.Stored; + uint lastMod = 0; + + zr = zf.OpenReadStream(i, false, out readStream, out streamsize, out cm, out lastMod); + + byte[] ibuffer = new byte[_bufferSize]; + int ilen; + while ((ilen = readStream.Read(ibuffer, 0, _bufferSize)) > 0) + { + st.Write(ibuffer, 0, ilen); + st.Flush(); + } + + zr = zf.CloseReadStream(); + } + } + break; } } catch (Exception ex) @@ -338,10 +372,6 @@ namespace SabreTools.Helper.Tools logger.Error(ex.ToString()); st = null; } - finally - { - reader?.Dispose(); - } st.Position = 0; return st;