1 // OpenArchive.h
2 
3 #ifndef __OPEN_ARCHIVE_H
4 #define __OPEN_ARCHIVE_H
5 
6 #include "../../../Windows/PropVariant.h"
7 
8 #include "ArchiveOpenCallback.h"
9 #include "LoadCodecs.h"
10 #include "Property.h"
11 
12 #ifndef _SFX
13 
14 #define SUPPORT_ALT_STREAMS
15 
16 #endif
17 
18 HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();
19 HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw();
20 HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw();
21 HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw();
22 HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw();
23 
24 #ifdef SUPPORT_ALT_STREAMS
25 int FindAltStreamColon_in_Path(const wchar_t *path);
26 #endif
27 
28 /*
29 struct COptionalOpenProperties
30 {
31   UString FormatName;
32   CObjectVector<CProperty> Props;
33 };
34 */
35 
36 #ifdef _SFX
37 #define OPEN_PROPS_DECL
38 #else
39 #define OPEN_PROPS_DECL const CObjectVector<CProperty> *props;
40 // #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props
41 #endif
42 
43 struct COpenSpecFlags
44 {
45   // bool CanReturnFull;
46   bool CanReturnFrontal;
47   bool CanReturnTail;
48   bool CanReturnMid;
49 
CanReturn_NonStartCOpenSpecFlags50   bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }
51 
COpenSpecFlagsCOpenSpecFlags52   COpenSpecFlags():
53     // CanReturnFull(true),
54     CanReturnFrontal(false),
55     CanReturnTail(false),
56     CanReturnMid(false)
57     {}
58 };
59 
60 struct COpenType
61 {
62   int FormatIndex;
63 
64   COpenSpecFlags SpecForcedType;
65   COpenSpecFlags SpecMainType;
66   COpenSpecFlags SpecWrongExt;
67   COpenSpecFlags SpecUnknownExt;
68 
69   bool Recursive;
70 
71   bool CanReturnArc;
72   bool CanReturnParser;
73   bool EachPos;
74 
75   // bool SkipSfxStub;
76   // bool ExeAsUnknown;
77 
78   bool ZerosTailIsAllowed;
79 
80   bool MaxStartOffset_Defined;
81   UInt64 MaxStartOffset;
82 
GetSpecCOpenType83   const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const
84   {
85     return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));
86   }
87 
COpenTypeCOpenType88   COpenType():
89       FormatIndex(-1),
90       Recursive(true),
91       EachPos(false),
92       CanReturnArc(true),
93       CanReturnParser(false),
94       // SkipSfxStub(true),
95       // ExeAsUnknown(true),
96       ZerosTailIsAllowed(false),
97       MaxStartOffset_Defined(false),
98       MaxStartOffset(0)
99   {
100     SpecForcedType.CanReturnFrontal = true;
101     SpecForcedType.CanReturnTail = true;
102     SpecForcedType.CanReturnMid = true;
103 
104     SpecMainType.CanReturnFrontal = true;
105 
106     SpecUnknownExt.CanReturnTail = true; // for sfx
107     SpecUnknownExt.CanReturnMid = true;
108     SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad
109 
110     // ZerosTailIsAllowed = true;
111   }
112 };
113 
114 struct COpenOptions
115 {
116   CCodecs *codecs;
117   COpenType openType;
118   const CObjectVector<COpenType> *types;
119   const CIntVector *excludedFormats;
120 
121   IInStream *stream;
122   ISequentialInStream *seqStream;
123   IArchiveOpenCallback *callback;
124   COpenCallbackImp *callbackSpec;
125   OPEN_PROPS_DECL
126   // bool openOnlySpecifiedByExtension,
127 
128   bool stdInMode;
129   UString filePath;
130 
COpenOptionsCOpenOptions131   COpenOptions():
132       codecs(NULL),
133       types(NULL),
134       excludedFormats(NULL),
135       stream(NULL),
136       seqStream(NULL),
137       callback(NULL),
138       callbackSpec(NULL),
139       stdInMode(false)
140     {}
141 
142 };
143 
144 UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);
145 
146 struct CArcErrorInfo
147 {
148   bool ThereIsTail;
149   bool UnexpecedEnd;
150   bool IgnoreTail; // all are zeros
151   // bool NonZerosTail;
152   bool ErrorFlags_Defined;
153   UInt32 ErrorFlags;
154   UInt32 WarningFlags;
155   int ErrorFormatIndex; // - 1 means no Error.
156                         // if FormatIndex == ErrorFormatIndex, the archive is open with offset
157   UInt64 TailSize;
158 
159   /* if CArc is Open OK with some format:
160         - ErrorFormatIndex shows error format index, if extension is incorrect
161         - other variables show message and warnings of archive that is open */
162 
163   UString ErrorMessage;
164   UString WarningMessage;
165 
166   // call IsArc_After_NonOpen only if Open returns S_FALSE
IsArc_After_NonOpenCArcErrorInfo167   bool IsArc_After_NonOpen() const
168   {
169     return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);
170   }
171 
172 
CArcErrorInfoCArcErrorInfo173   CArcErrorInfo():
174       ThereIsTail(false),
175       UnexpecedEnd(false),
176       IgnoreTail(false),
177       // NonZerosTail(false),
178       ErrorFlags_Defined(false),
179       ErrorFlags(0),
180       WarningFlags(0),
181       ErrorFormatIndex(-1),
182       TailSize(0)
183     {}
184 
185   void ClearErrors();
186 
ClearErrors_FullCArcErrorInfo187   void ClearErrors_Full()
188   {
189     ErrorFormatIndex = -1;
190     ClearErrors();
191   }
192 
IsThereErrorOrWarningCArcErrorInfo193   bool IsThereErrorOrWarning() const
194   {
195     return ErrorFlags != 0
196         || WarningFlags != 0
197         || NeedTailWarning()
198         || UnexpecedEnd
199         || !ErrorMessage.IsEmpty()
200         || !WarningMessage.IsEmpty();
201   }
202 
AreThereErrorsCArcErrorInfo203   bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }
AreThereWarningsCArcErrorInfo204   bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }
205 
NeedTailWarningCArcErrorInfo206   bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; }
207 
GetWarningFlagsCArcErrorInfo208   UInt32 GetWarningFlags() const
209   {
210     UInt32 a = WarningFlags;
211     if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0)
212       a |= kpv_ErrorFlags_DataAfterEnd;
213     return a;
214   }
215 
GetErrorFlagsCArcErrorInfo216   UInt32 GetErrorFlags() const
217   {
218     UInt32 a = ErrorFlags;
219     if (UnexpecedEnd)
220       a |= kpv_ErrorFlags_UnexpectedEnd;
221     return a;
222   }
223 };
224 
225 struct CReadArcItem
226 {
227   UString Path;            // Path from root (including alt stream name, if alt stream)
228   UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode
229 
230   #ifdef SUPPORT_ALT_STREAMS
231   UString MainPath;
232                 /* MainPath = Path for non-AltStream,
233                    MainPath = Path of parent, if there is parent for AltStream. */
234   UString AltStreamName;
235   bool IsAltStream;
236   bool WriteToAltStreamIfColon;
237   #endif
238 
239   bool IsDir;
240   bool MainIsDir;
241   UInt32 ParentIndex; // use it, if IsAltStream
242 
243   #ifndef _SFX
244   bool _use_baseParentFolder_mode;
245   int _baseParentFolder;
246   #endif
247 
CReadArcItemCReadArcItem248   CReadArcItem()
249   {
250     #ifdef SUPPORT_ALT_STREAMS
251     WriteToAltStreamIfColon = false;
252     #endif
253 
254     #ifndef _SFX
255     _use_baseParentFolder_mode = false;
256     _baseParentFolder = -1;
257     #endif
258   }
259 };
260 
261 class CArc
262 {
263   HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);
264   HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);
265   HRESULT OpenStream2(const COpenOptions &options);
266 
267   #ifndef _SFX
268   // parts.Back() can contain alt stream name "nams:AltName"
269   HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
270   #endif
271 
272 public:
273   CMyComPtr<IInArchive> Archive;
274   CMyComPtr<IInStream> InStream;
275           // we use InStream in 2 cases (ArcStreamOffset != 0):
276           // 1) if we use additional cache stream
277           // 2) we reopen sfx archive with CTailInStream
278 
279   CMyComPtr<IArchiveGetRawProps> GetRawProps;
280   CMyComPtr<IArchiveGetRootProps> GetRootProps;
281 
282   CArcErrorInfo ErrorInfo; // for OK archives
283   CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)
284 
285   UString Path;
286   UString filePath;
287   UString DefaultName;
288   int FormatIndex; // - 1 means Parser.
289   int SubfileIndex;
290   FILETIME MTime;
291   bool MTimeDefined;
292 
293   Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler
294   UInt64 PhySize;
295   // UInt64 OkPhySize;
296   bool PhySizeDefined;
297   // bool OkPhySize_Defined;
298   UInt64 FileSize;
299   UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file
300   // bool offsetDefined;
301 
GetEstmatedPhySize()302   UInt64 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; }
303 
304   UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler
GetGlobalOffset()305   Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive
306 
307   // AString ErrorFlagsText;
308 
309   bool IsParseArc;
310 
311   bool IsTree;
312   bool IsReadOnly;
313 
314   bool Ask_Deleted;
315   bool Ask_AltStream;
316   bool Ask_Aux;
317   bool Ask_INode;
318 
319   bool IgnoreSplit; // don't try split handler
320 
321   // void Set_ErrorFlagsText();
322 
CArc()323   CArc():
324     MTimeDefined(false),
325     IsTree(false),
326     IsReadOnly(false),
327     Ask_Deleted(false),
328     Ask_AltStream(false),
329     Ask_Aux(false),
330     Ask_INode(false),
331     IgnoreSplit(false)
332     {}
333 
334   HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes);
335 
336   // ~CArc();
337 
Close()338   HRESULT Close()
339   {
340     InStream.Release();
341     return Archive->Close();
342   }
343 
344   HRESULT GetItemPath(UInt32 index, UString &result) const;
345   HRESULT GetDefaultItemPath(UInt32 index, UString &result) const;
346 
347   // GetItemPath2 adds [DELETED] dir prefix for deleted items.
348   HRESULT GetItemPath2(UInt32 index, UString &result) const;
349 
350   HRESULT GetItem(UInt32 index, CReadArcItem &item) const;
351 
352   HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const;
353   HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const;
IsItemAnti(UInt32 index,bool & result)354   HRESULT IsItemAnti(UInt32 index, bool &result) const
355     { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); }
356 
357 
358   HRESULT OpenStream(const COpenOptions &options);
359   HRESULT OpenStreamOrFile(COpenOptions &options);
360 
361   HRESULT ReOpen(const COpenOptions &options);
362 
363   HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);
364 };
365 
366 struct CArchiveLink
367 {
368   CObjectVector<CArc> Arcs;
369   UStringVector VolumePaths;
370   UInt64 VolumesSize;
371   bool IsOpen;
372 
373   bool PasswordWasAsked;
374   // UString Password;
375 
376   // int NonOpenErrorFormatIndex; // - 1 means no Error.
377   UString NonOpen_ArcPath;
378 
379   CArcErrorInfo NonOpen_ErrorInfo;
380 
381   // UString ErrorsText;
382   // void Set_ErrorsText();
383 
CArchiveLinkCArchiveLink384   CArchiveLink():
385       VolumesSize(0),
386       IsOpen(false),
387       PasswordWasAsked(false)
388       {}
389 
390   void KeepModeForNextOpen();
391   HRESULT Close();
392   void Release();
~CArchiveLinkCArchiveLink393   ~CArchiveLink() { Release(); }
394 
GetArcCArchiveLink395   const CArc *GetArc() const { return &Arcs.Back(); }
GetArchiveCArchiveLink396   IInArchive *GetArchive() const { return Arcs.Back().Archive; }
GetArchiveGetRawPropsCArchiveLink397   IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; }
GetArchiveGetRootPropsCArchiveLink398   IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }
399 
400   HRESULT Open(COpenOptions &options);
401   HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);
402   HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI);
403 
Open_StrictCArchiveLink404   HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI)
405   {
406     HRESULT result = Open3(options, callbackUI);
407     if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
408       result = S_FALSE;
409     return result;
410   }
411 
412   HRESULT ReOpen(COpenOptions &options);
413 };
414 
415 bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
416 
417 
418 struct CDirPathSortPair
419 {
420   unsigned Len;
421   unsigned Index;
422 
423   void SetNumSlashes(const FChar *s);
424 
CompareCDirPathSortPair425   int Compare(const CDirPathSortPair &a) const
426   {
427     // We need sorting order where parent items will be after child items
428     if (Len < a.Len) return 1;
429     if (Len > a.Len) return -1;
430     if (Index < a.Index) return -1;
431     if (Index > a.Index) return 1;
432     return 0;
433   }
434 };
435 
436 #endif
437