diff --git a/SabreTools.Library/FileTypes/SevenZipArchive.cs b/SabreTools.Library/FileTypes/SevenZipArchive.cs
index bdddf6fa..7ae2b907 100644
--- a/SabreTools.Library/FileTypes/SevenZipArchive.cs
+++ b/SabreTools.Library/FileTypes/SevenZipArchive.cs
@@ -19,7 +19,7 @@ using SeekOrigin = System.IO.SeekOrigin;
using Stream = System.IO.Stream;
#endif
using ROMVault2.SupportedFiles.Zip;
-using SevenZip;
+using SevenZip; // TODO: Remove this when 7zip write is implemented in SharpCompress
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Common;
diff --git a/SabreTools.Library/FileTypes/XZArchive.cs b/SabreTools.Library/FileTypes/XZArchive.cs
index 95e8b65b..1004af90 100644
--- a/SabreTools.Library/FileTypes/XZArchive.cs
+++ b/SabreTools.Library/FileTypes/XZArchive.cs
@@ -19,6 +19,9 @@ using Stream = System.IO.Stream;
#endif
using ROMVault2.SupportedFiles.Zip;
using SevenZip;
+using SharpCompress.Archives;
+using SharpCompress.Archives.SevenZip;
+using SharpCompress.Readers;
namespace SabreTools.Library.FileTypes
{
@@ -60,7 +63,37 @@ namespace SabreTools.Library.FileTypes
/// True if the extraction was a success, false otherwise
public override bool ExtractAll(string outDir)
{
- throw new NotImplementedException();
+ bool encounteredErrors = true;
+
+ try
+ {
+ // Create the temp directory
+ Directory.CreateDirectory(outDir);
+
+ // Extract all files to the temp directory
+ SharpCompress.Archives.SevenZip.SevenZipArchive sza = SharpCompress.Archives.SevenZip.SevenZipArchive.Open(Utilities.TryOpenRead(_filename));
+ foreach (SevenZipArchiveEntry entry in sza.Entries)
+ {
+ entry.WriteToDirectory(outDir, new ExtractionOptions { PreserveFileTime = true, ExtractFullPath = true, Overwrite = true });
+ }
+ encounteredErrors = false;
+ sza.Dispose();
+ }
+ catch (EndOfStreamException)
+ {
+ // Catch this but don't count it as an error because SharpCompress is unsafe
+ }
+ catch (InvalidOperationException)
+ {
+ encounteredErrors = true;
+ }
+ catch (Exception)
+ {
+ // Don't log file open errors
+ encounteredErrors = true;
+ }
+
+ return encounteredErrors;
}
///
@@ -71,7 +104,42 @@ namespace SabreTools.Library.FileTypes
/// Name of the extracted file, null on error
public override string ExtractEntry(string entryName, string outDir)
{
- throw new NotImplementedException();
+ // Try to extract a stream using the given information
+ (MemoryStream ms, string realEntry) = ExtractEntryStream(entryName);
+
+ // If the memory stream and the entry name are both non-null, we write to file
+ if (ms != null && realEntry != null)
+ {
+ realEntry = Path.Combine(outDir, realEntry);
+
+ // Create the output subfolder now
+ Directory.CreateDirectory(Path.GetDirectoryName(realEntry));
+
+ // Now open and write the file if possible
+ FileStream fs = Utilities.TryCreate(realEntry);
+ if (fs != null)
+ {
+ ms.Seek(0, SeekOrigin.Begin);
+ byte[] zbuffer = new byte[_bufferSize];
+ int zlen;
+ while ((zlen = ms.Read(zbuffer, 0, _bufferSize)) > 0)
+ {
+ fs.Write(zbuffer, 0, zlen);
+ fs.Flush();
+ }
+
+ ms?.Dispose();
+ fs?.Dispose();
+ }
+ else
+ {
+ ms?.Dispose();
+ fs?.Dispose();
+ realEntry = null;
+ }
+ }
+
+ return realEntry;
}
///
@@ -82,7 +150,32 @@ namespace SabreTools.Library.FileTypes
/// MemoryStream representing the entry, null on error
public override (MemoryStream, string) ExtractEntryStream(string entryName)
{
- throw new NotImplementedException();
+ MemoryStream ms = new MemoryStream();
+ string realEntry = null;
+
+ try
+ {
+ SharpCompress.Archives.SevenZip.SevenZipArchive sza = SharpCompress.Archives.SevenZip.SevenZipArchive.Open(_filename, new ReaderOptions { LeaveStreamOpen = false, });
+ foreach (SevenZipArchiveEntry entry in sza.Entries)
+ {
+ if (entry != null && !entry.IsDirectory && entry.Key.Contains(entryName))
+ {
+ // Write the file out
+ realEntry = entry.Key;
+ entry.WriteTo(ms);
+ break;
+ }
+ }
+ sza.Dispose();
+ }
+ catch (Exception ex)
+ {
+ Globals.Logger.Error(ex.ToString());
+ ms = null;
+ realEntry = null;
+ }
+
+ return (ms, realEntry);
}
#endregion