Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 77 additions & 17 deletions src/FileTypeDetection/Infrastructure/ArchiveInternals.vb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
Option Explicit On

Imports System.IO
Imports System.Reflection
Imports System.Security

Namespace Global.Tomtastisch.FileClassifier
''' <summary>
Expand Down Expand Up @@ -126,8 +128,13 @@
Friend Shared Function OpenArchive(stream As Stream) As SharpCompress.Archives.IArchive
Try
Dim options = New SharpCompress.Readers.ReaderOptions() With {.LeaveStreamOpen = True}
Return SharpCompress.Archives.ArchiveFactory.OpenArchive(stream, options)
Return OpenArchiveFactoryCompat(stream, options)
Catch ex As TargetInvocationException When IsExpectedInvocationException(ex)
Return Nothing
Catch ex As TargetInvocationException
Throw
Catch ex As Exception When _
TypeOf ex Is MissingMethodException OrElse
TypeOf ex Is InvalidOperationException OrElse
TypeOf ex Is NotSupportedException OrElse
TypeOf ex Is ArgumentException
Expand Down Expand Up @@ -158,14 +165,67 @@
Private Shared Function OpenGZipArchive(stream As Stream) As SharpCompress.Archives.IArchive
Try
Dim options = New SharpCompress.Readers.ReaderOptions() With {.LeaveStreamOpen = True}
Return SharpCompress.Archives.GZip.GZipArchive.OpenArchive(stream, options)
Return OpenGZipArchiveCompat(stream, options)
Catch ex As TargetInvocationException When IsExpectedInvocationException(ex)
Return Nothing
Catch ex As TargetInvocationException
Throw
Catch ex As Exception When _
TypeOf ex Is MissingMethodException OrElse
TypeOf ex Is InvalidOperationException OrElse
TypeOf ex Is NotSupportedException OrElse
TypeOf ex Is ArgumentException
Return Nothing
End Try
End Function

Private Shared Function IsExpectedInvocationException(ex As TargetInvocationException) As Boolean
Dim inner = ex?.InnerException
If inner Is Nothing Then Return False

Return TypeOf inner Is InvalidOperationException OrElse
TypeOf inner Is NotSupportedException OrElse
TypeOf inner Is ArgumentException OrElse
TypeOf inner Is InvalidDataException OrElse
TypeOf inner Is IOException
End Function

Private Shared Function OpenArchiveFactoryCompat(
stream As Stream,
options As SharpCompress.Readers.ReaderOptions
) As SharpCompress.Archives.IArchive
Dim method = GetOpenCompatMethod(GetType(SharpCompress.Archives.ArchiveFactory))
Dim opened = method.Invoke(Nothing, New Object() {stream, options})
Return CType(opened, SharpCompress.Archives.IArchive)
End Function

Private Shared Function OpenGZipArchiveCompat(
stream As Stream,
options As SharpCompress.Readers.ReaderOptions
) As SharpCompress.Archives.IArchive
Dim method = GetOpenCompatMethod(GetType(SharpCompress.Archives.GZip.GZipArchive))
Dim opened = method.Invoke(Nothing, New Object() {stream, options})
Return CType(opened, SharpCompress.Archives.IArchive)
End Function

Private Shared Function GetOpenCompatMethod(type As Type) As System.Reflection.MethodInfo

Check warning on line 211 in src/FileTypeDetection/Infrastructure/ArchiveInternals.vb

View workflow job for this annotation

GitHub Actions / qodana

Redundant qualifier

Qualifier is redundant
Dim signature = New Type() {GetType(Stream), GetType(SharpCompress.Readers.ReaderOptions)}
Dim method = type.GetMethod("OpenArchive", BindingFlags.Public Or
BindingFlags.Static,
binder:=Nothing,
types:=signature,
modifiers:=Nothing)
If method IsNot Nothing Then Return method

method = type.GetMethod("Open", BindingFlags.Public Or
BindingFlags.Static,
binder:=Nothing,
types:=signature,
modifiers:=Nothing)
If method IsNot Nothing Then Return method

Throw New MissingMethodException(type.FullName, "OpenArchive/Open(Stream, ReaderOptions)")
End Function
End Class

''' <summary>
Expand All @@ -187,7 +247,7 @@
End Using
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is InvalidDataException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand Down Expand Up @@ -227,7 +287,7 @@
End Using
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is InvalidDataException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand All @@ -242,7 +302,7 @@
StreamGuard.RewindToStart(stream)
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is NotSupportedException OrElse
TypeOf ex Is ArgumentException OrElse
Expand Down Expand Up @@ -351,7 +411,7 @@
Return entries.AsReadOnly()
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is InvalidDataException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand Down Expand Up @@ -389,7 +449,7 @@
destinationFull = Path.GetFullPath(destinationDirectory)
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is PathTooLongException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand Down Expand Up @@ -425,7 +485,7 @@
Return True
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is InvalidDataException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand All @@ -440,7 +500,7 @@
Directory.Delete(stageDir, recursive:=True)
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is NotSupportedException OrElse
TypeOf ex Is ArgumentException
Expand All @@ -466,7 +526,7 @@
targetPath = Path.GetFullPath(Path.Combine(destinationPrefix, entryName))
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is PathTooLongException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand Down Expand Up @@ -509,7 +569,7 @@
Return True
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is InvalidDataException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand Down Expand Up @@ -551,7 +611,7 @@
Return True
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is InvalidDataException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand Down Expand Up @@ -650,7 +710,7 @@
End Using
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is InvalidDataException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand Down Expand Up @@ -680,7 +740,7 @@
End Using
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is InvalidDataException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand Down Expand Up @@ -793,7 +853,7 @@
Return True
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is InvalidDataException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand Down Expand Up @@ -883,7 +943,7 @@
End Using
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is InvalidDataException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand Down Expand Up @@ -943,7 +1003,7 @@
Return True
Catch ex As Exception When _
TypeOf ex Is UnauthorizedAccessException OrElse
TypeOf ex Is System.Security.SecurityException OrElse
TypeOf ex Is SecurityException OrElse
TypeOf ex Is IOException OrElse
TypeOf ex Is InvalidDataException OrElse
TypeOf ex Is NotSupportedException OrElse
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ internal static class ArchivePayloadFactory
internal static byte[] CreateZipWithSingleEntry(string entryName, string content)
{
using var ms = new MemoryStream();
using (var writer = WriterFactory.OpenWriter(ms, ArchiveType.Zip, new WriterOptions(CompressionType.Deflate)))
using (var writer = SharpCompressApiCompat.OpenWriter(ms, ArchiveType.Zip, new WriterOptions(CompressionType.Deflate)))
using (var payload = new MemoryStream(Encoding.UTF8.GetBytes(content)))
{
writer.Write(string.IsNullOrWhiteSpace(entryName) ? "note.txt" : entryName, payload, DateTime.UnixEpoch);
Expand All @@ -22,7 +22,7 @@ internal static byte[] CreateZipWithSingleEntry(string entryName, string content
internal static byte[] CreateTarWithSingleEntry(string entryName, string content)
{
using var ms = new MemoryStream();
using (var writer = WriterFactory.OpenWriter(ms, ArchiveType.Tar, new WriterOptions(CompressionType.None)))
using (var writer = SharpCompressApiCompat.OpenWriter(ms, ArchiveType.Tar, new WriterOptions(CompressionType.None)))
using (var payload = new MemoryStream(Encoding.UTF8.GetBytes(content)))
{
writer.Write(string.IsNullOrWhiteSpace(entryName) ? "note.txt" : entryName, payload, DateTime.UnixEpoch);
Expand All @@ -34,7 +34,7 @@ internal static byte[] CreateTarWithSingleEntry(string entryName, string content
internal static byte[] CreateGZipWithSingleEntry(string entryName, byte[] payload)
{
using var ms = new MemoryStream();
using (var writer = WriterFactory.OpenWriter(ms, ArchiveType.GZip, new WriterOptions(CompressionType.GZip)))
using (var writer = SharpCompressApiCompat.OpenWriter(ms, ArchiveType.GZip, new WriterOptions(CompressionType.GZip)))
using (var source = new MemoryStream(payload, false))
{
writer.Write(string.IsNullOrWhiteSpace(entryName) ? "payload.bin" : entryName, source, DateTime.UnixEpoch);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Writers;

namespace FileTypeDetectionLib.Tests.Support;

internal static class SharpCompressApiCompat
{
internal static IArchive OpenArchive(Stream stream)
{
var options = new ReaderOptions { LeaveStreamOpen = true };
var opened = InvokeOpen(typeof(ArchiveFactory), stream, options);
return (IArchive)opened;
}

internal static IArchive OpenZipArchive(Stream stream)
{
var options = new ReaderOptions { LeaveStreamOpen = true };
var opened = InvokeOpen(typeof(ZipArchive), stream, options);
return (IArchive)opened;
}

internal static IWriter OpenWriter(Stream stream, ArchiveType archiveType, WriterOptions options)
{
var args = new object[] { stream, archiveType, options };
var signature = new[] { typeof(Stream), typeof(ArchiveType), typeof(WriterOptions) };

var method = typeof(WriterFactory).GetMethod("OpenWriter", signature)
?? typeof(WriterFactory).GetMethod("Open", signature)
?? throw new MissingMethodException(typeof(WriterFactory).FullName, "OpenWriter/Open(Stream, ArchiveType, WriterOptions) [compat]");

return (IWriter)method.Invoke(null, args)!;
}

private static object InvokeOpen(Type type, Stream stream, ReaderOptions options)
{
var args = new object[] { stream, options };
var signature = new[] { typeof(Stream), typeof(ReaderOptions) };

var method = type.GetMethod("OpenArchive", signature)
?? type.GetMethod("Open", signature)
?? throw new MissingMethodException(type.FullName, "OpenArchive/Open(Stream, ReaderOptions)");

return method.Invoke(null, args)!;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
using System.Reflection;
using FileTypeDetectionLib.Tests.Support;
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Writers;
using Tomtastisch.FileClassifier;

Expand Down Expand Up @@ -86,14 +84,14 @@ public void TryReadEntryPayloadBoundedWithOptions_ReturnsFalse_ForInvalidInputs(
private static IArchiveEntry CreateZipArchiveEntry(string name, byte[] payload)
{
using var ms = new MemoryStream();
using (var writer = WriterFactory.OpenWriter(ms, ArchiveType.Zip, new WriterOptions(CompressionType.Deflate)))
using (var writer = SharpCompressApiCompat.OpenWriter(ms, ArchiveType.Zip, new WriterOptions(CompressionType.Deflate)))
using (var data = new MemoryStream(payload, false))
{
writer.Write(name, data, DateTime.UnixEpoch);
}

ms.Position = 0;
var archive = ZipArchive.OpenArchive(ms, new ReaderOptions { LeaveStreamOpen = true });
var archive = SharpCompressApiCompat.OpenZipArchive(ms);
return archive.Entries.First();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using FileTypeDetectionLib.Tests.Support;
using Microsoft.Extensions.Logging;
using SharpCompress.Archives;
using SharpCompress.Common;
using SharpCompress.Readers;
using Tomtastisch.FileClassifier;

namespace FileTypeDetectionLib.Tests.Unit;
Expand Down Expand Up @@ -162,7 +160,7 @@ public void SharpCompressEntryModel_MapsArchiveEntryFields_ForConcreteEntry()
{
var payload = ArchivePayloadFactory.CreateTarWithSingleEntry("inner/note.txt", "hello");
using var ms = new MemoryStream(payload, false);
using var archive = ArchiveFactory.OpenArchive(ms, new ReaderOptions { LeaveStreamOpen = true });
using var archive = SharpCompressApiCompat.OpenArchive(ms);
var entry = archive.Entries.First(e => !e.IsDirectory);
var model = new SharpCompressEntryModel(entry);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public void Process_ReturnsFalse_WhenExtractorReturnsFalse()
private static byte[] CreateTarWithEntries(int entryCount, int entrySize)
{
using var ms = new MemoryStream();
using (var writer = WriterFactory.OpenWriter(ms, ArchiveType.Tar, new WriterOptions(CompressionType.None)))
using (var writer = SharpCompressApiCompat.OpenWriter(ms, ArchiveType.Tar, new WriterOptions(CompressionType.None)))
{
for (var i = 0; i < entryCount; i++)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Text;
using SharpCompress.Archives;
using FileTypeDetectionLib.Tests.Support;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Writers;
using Tomtastisch.FileClassifier;

Expand All @@ -14,7 +13,7 @@ public void Properties_ReturnValues_ForRealArchiveEntry()
{
var payload = CreateTarWithEntry("note.txt", "hello");
using var stream = new MemoryStream(payload, false);
using var archive = ArchiveFactory.OpenArchive(stream, new ReaderOptions { LeaveStreamOpen = true });
using var archive = SharpCompressApiCompat.OpenArchive(stream);

var entry = archive.Entries.First();
var model = new SharpCompressEntryModel(entry);
Expand All @@ -31,7 +30,7 @@ public void Properties_ReturnValues_ForRealArchiveEntry()
private static byte[] CreateTarWithEntry(string name, string content)
{
using var ms = new MemoryStream();
using (var writer = WriterFactory.OpenWriter(ms, ArchiveType.Tar, new WriterOptions(CompressionType.None)))
using (var writer = SharpCompressApiCompat.OpenWriter(ms, ArchiveType.Tar, new WriterOptions(CompressionType.None)))
using (var data = new MemoryStream(Encoding.UTF8.GetBytes(content)))
{
writer.Write(name, data, DateTime.UnixEpoch);
Expand Down
Loading