11using System ;
22using System . IO ;
3+ using SabreTools . Models . ArchiveDotOrg ;
34
45namespace SabreTools . Serialization . Wrappers
56{
@@ -17,9 +18,24 @@ public partial class MicrosoftCabinet : WrapperBase<Models.MicrosoftCabinet.Cabi
1718 /// <inheritdoc cref="Models.MicrosoftCabinet.Cabinet.Files"/>
1819 public Models . MicrosoftCabinet . CFFILE [ ] ? Files => Model . Files ;
1920
21+ /// <inheritdoc cref="Models.MicrosoftCabinet.CFHEADER.FileCount"/>
22+ public int FileCount => Model . Header ? . FileCount ?? 0 ;
23+
2024 /// <inheritdoc cref="Models.MicrosoftCabinet.Cabinet.Folders"/>
2125 public Models . MicrosoftCabinet . CFFOLDER [ ] ? Folders => Model . Folders ;
2226
27+ /// <inheritdoc cref="Models.MicrosoftCabinet.CFHEADER.FolderCount"/>
28+ public int FolderCount => Model . Header ? . FolderCount ?? 0 ;
29+
30+ /// <inheritdoc cref="Models.MicrosoftCabinet.Cabinet.Header"/>
31+ public Models . MicrosoftCabinet . CFHEADER ? Header => Model . Header ;
32+
33+ /// <summary>
34+ /// Reference to the next cabinet header
35+ /// </summary>
36+ /// <remarks>Only used in multi-file</remarks>
37+ public MicrosoftCabinet ? Next { get ; set ; }
38+
2339 #endregion
2440
2541 #region Constructors
@@ -86,6 +102,88 @@ public MicrosoftCabinet(Models.MicrosoftCabinet.Cabinet? model, Stream? data)
86102
87103 #endregion
88104
105+ #region Cabinet Set
106+
107+ /// <summary>
108+ /// Open a cabinet set for reading, if possible
109+ /// </summary>
110+ /// <param name="filename">Filename for one cabinet in the set</param>
111+ /// <returns>Wrapper representing the set, null on error</returns>
112+ public static MicrosoftCabinet ? OpenSet ( string ? filename )
113+ {
114+ // If the file is invalid
115+ if ( string . IsNullOrEmpty ( filename ) )
116+ return null ;
117+ else if ( ! File . Exists ( filename ! ) )
118+ return null ;
119+
120+ // Get the full file path and directory
121+ filename = Path . GetFullPath ( filename ) ;
122+ string ? directory = Path . GetDirectoryName ( filename ) ;
123+
124+ // Read in the current file and try to parse
125+ var stream = File . Open ( filename , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) ;
126+ var current = Create ( stream ) ;
127+ if ( current ? . Header == null )
128+ return null ;
129+
130+ // Seek to the first part of the cabinet set
131+ while ( current . Header . CabinetPrev != null )
132+ {
133+ // Get the path defined in the current header
134+ string prevPath = current . Header . CabinetPrev ;
135+ if ( directory != null )
136+ prevPath = Path . Combine ( directory , prevPath ) ;
137+
138+ // If the file doesn't exist
139+ if ( ! File . Exists ( prevPath ) )
140+ break ;
141+
142+ // Close the previous cabinet part to avoid locking issues
143+ stream . Close ( ) ;
144+
145+ // Open the previous cabinet and try to parse
146+ stream = File . Open ( prevPath , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) ;
147+ var prev = Create ( stream ) ;
148+ if ( prev ? . Header == null )
149+ break ;
150+
151+ // Assign previous as new current
152+ current = prev ;
153+ }
154+
155+ // Cache the current start of the cabinet set
156+ var start = current ;
157+
158+ // Read in the cabinet parts sequentially
159+ while ( current . Header . CabinetNext != null )
160+ {
161+ // Get the path defined in the current header
162+ string nextPath = current . Header . CabinetNext ;
163+ if ( directory != null )
164+ nextPath = Path . Combine ( directory , nextPath ) ;
165+
166+ // If the file doesn't exist
167+ if ( ! File . Exists ( nextPath ) )
168+ break ;
169+
170+ // Open the next cabinet and try to parse
171+ stream = File . Open ( nextPath , FileMode . Open , FileAccess . Read , FileShare . ReadWrite ) ;
172+ var next = Create ( stream ) ;
173+ if ( next ? . Header == null )
174+ break ;
175+
176+ // Add next to the current and reset current
177+ current . Next = next ;
178+ current = next ;
179+ }
180+
181+ // Return the start of the set
182+ return start ;
183+ }
184+
185+ #endregion
186+
89187 #region Checksumming
90188
91189 /// <summary>
0 commit comments