4
4
#if NET462_OR_GREATER || NETCOREAPP
5
5
using SharpCompress . Archives ;
6
6
using SharpCompress . Archives . SevenZip ;
7
+ using SharpCompress . Common ;
7
8
using SharpCompress . Readers ;
8
9
#endif
9
10
@@ -43,50 +44,91 @@ public bool Extract(Stream? stream, string file, string outDir, bool lookForHead
43
44
{
44
45
var readerOptions = new ReaderOptions ( ) { LookForHeader = lookForHeader } ;
45
46
var sevenZip = SevenZipArchive . Open ( stream , readerOptions ) ;
46
-
47
47
// Try to read the file path if no entries are found
48
48
if ( sevenZip . Entries . Count == 0 && ! string . IsNullOrEmpty ( file ) && File . Exists ( file ) )
49
49
sevenZip = SevenZipArchive . Open ( file , readerOptions ) ;
50
50
51
- foreach ( var entry in sevenZip . Entries )
51
+ // Currently doesn't flag solid 7z archives with only 1 solid block as solid, but practically speaking
52
+ // this is not much of a concern.
53
+ if ( sevenZip . IsSolid )
54
+ return ExtractSolid ( sevenZip , outDir , includeDebug ) ;
55
+ else
56
+ return ExtractNonSolid ( sevenZip , outDir , includeDebug ) ;
57
+
58
+ }
59
+ catch ( Exception ex )
60
+ {
61
+ if ( includeDebug ) Console . WriteLine ( ex ) ;
62
+ return false ;
63
+ }
64
+ #else
65
+ return false ;
66
+ #endif
67
+ }
68
+
69
+ #if NET462_OR_GREATER || NETCOREAPP
70
+ /// <summary>
71
+ /// Extraction method for non-solid archives. This iterates over each entry in the archive to extract every
72
+ /// file individually, in order to extract all valid files from the archive.
73
+ /// </summary>
74
+ private bool ExtractNonSolid ( SevenZipArchive sevenZip , string outDir , bool includeDebug )
75
+ {
76
+ foreach ( var entry in sevenZip . Entries )
77
+ {
78
+ try
52
79
{
53
- try
54
- {
55
- // If the entry is a directory
56
- if ( entry . IsDirectory )
57
- continue ;
80
+ // If the entry is a directory
81
+ if ( entry . IsDirectory )
82
+ continue ;
58
83
59
- // If the entry has an invalid key
60
- if ( entry . Key == null )
61
- continue ;
84
+ // If the entry has an invalid key
85
+ if ( entry . Key == null )
86
+ continue ;
62
87
63
- // If we have a partial entry due to an incomplete multi-part archive, skip it
64
- if ( ! entry . IsComplete )
65
- continue ;
88
+ // If we have a partial entry due to an incomplete multi-part archive, skip it
89
+ if ( ! entry . IsComplete )
90
+ continue ;
66
91
67
- string tempFile = Path . Combine ( outDir , entry . Key ) ;
68
- var directoryName = Path . GetDirectoryName ( tempFile ) ;
69
- if ( directoryName != null && ! Directory . Exists ( directoryName ) )
70
- Directory . CreateDirectory ( directoryName ) ;
92
+ string tempFile = Path . Combine ( outDir , entry . Key ) ;
93
+ var directoryName = Path . GetDirectoryName ( tempFile ) ;
94
+ if ( directoryName != null && ! Directory . Exists ( directoryName ) )
95
+ Directory . CreateDirectory ( directoryName ) ;
71
96
72
- entry . WriteToFile ( tempFile ) ;
73
- }
74
- catch ( Exception ex )
75
- {
76
- if ( includeDebug ) Console . WriteLine ( ex ) ;
77
- }
97
+ entry . WriteToFile ( tempFile ) ;
98
+ }
99
+ catch ( Exception ex )
100
+ {
101
+ if ( includeDebug ) Console . WriteLine ( ex ) ;
78
102
}
79
-
80
- return true ;
103
+ }
104
+ return true ;
105
+ }
106
+
107
+ /// <summary>
108
+ /// Extraction method for solid archives. Uses ExtractAllEntries because extraction for solid archives must be
109
+ /// done sequentially, and files beyond a corrupted point in a solid archive will be unreadable anyways.
110
+ /// </summary>
111
+ private bool ExtractSolid ( SevenZipArchive sevenZip , string outDir , bool includeDebug )
112
+ {
113
+ try
114
+ {
115
+ if ( ! Directory . Exists ( outDir ) )
116
+ Directory . CreateDirectory ( outDir ) ;
117
+
118
+ sevenZip . WriteToDirectory ( outDir , new ExtractionOptions ( )
119
+ {
120
+ ExtractFullPath = true ,
121
+ Overwrite = true ,
122
+ } ) ;
123
+
81
124
}
82
125
catch ( Exception ex )
83
126
{
84
127
if ( includeDebug ) Console . WriteLine ( ex ) ;
85
- return false ;
86
128
}
87
- #else
88
- return false ;
89
- #endif
129
+
130
+ return true ;
90
131
}
132
+ #endif
91
133
}
92
- }
134
+ }
0 commit comments