• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // OpenArchive.h
2 
3 #ifndef ZIP7_INC_OPEN_ARCHIVE_H
4 #define ZIP7_INC_OPEN_ARCHIVE_H
5 
6 #include "../../../Windows/PropVariant.h"
7 
8 #include "ArchiveOpenCallback.h"
9 #include "LoadCodecs.h"
10 #include "Property.h"
11 #include "DirItem.h"
12 
13 #ifndef Z7_SFX
14 
15 #define SUPPORT_ALT_STREAMS
16 
17 #endif
18 
19 HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();
20 HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw();
21 HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw();
22 HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw();
23 HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw();
24 
25 #ifdef SUPPORT_ALT_STREAMS
26 int FindAltStreamColon_in_Path(const wchar_t *path);
27 #endif
28 
29 /*
30 struct COptionalOpenProperties
31 {
32   UString FormatName;
33   CObjectVector<CProperty> Props;
34 };
35 */
36 
37 #ifdef Z7_SFX
38 #define OPEN_PROPS_DECL
39 #else
40 #define OPEN_PROPS_DECL const CObjectVector<CProperty> *props;
41 // #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props
42 #endif
43 
44 struct COpenSpecFlags
45 {
46   // bool CanReturnFull;
47   bool CanReturnFrontal;
48   bool CanReturnTail;
49   bool CanReturnMid;
50 
CanReturn_NonStartCOpenSpecFlags51   bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }
52 
COpenSpecFlagsCOpenSpecFlags53   COpenSpecFlags():
54     // CanReturnFull(true),
55     CanReturnFrontal(false),
56     CanReturnTail(false),
57     CanReturnMid(false)
58     {}
59 };
60 
61 struct COpenType
62 {
63   int FormatIndex;
64 
65   COpenSpecFlags SpecForcedType;
66   COpenSpecFlags SpecMainType;
67   COpenSpecFlags SpecWrongExt;
68   COpenSpecFlags SpecUnknownExt;
69 
70   bool Recursive;
71 
72   bool CanReturnArc;
73   bool CanReturnParser;
74   bool IsHashType;
75   bool EachPos;
76 
77   // bool SkipSfxStub;
78   // bool ExeAsUnknown;
79 
80   bool ZerosTailIsAllowed;
81 
82   bool MaxStartOffset_Defined;
83   UInt64 MaxStartOffset;
84 
GetSpecCOpenType85   const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const
86   {
87     return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));
88   }
89 
COpenTypeCOpenType90   COpenType():
91       FormatIndex(-1),
92       Recursive(true),
93       CanReturnArc(true),
94       CanReturnParser(false),
95       IsHashType(false),
96       EachPos(false),
97       // SkipSfxStub(true),
98       // ExeAsUnknown(true),
99       ZerosTailIsAllowed(false),
100       MaxStartOffset_Defined(false),
101       MaxStartOffset(0)
102   {
103     SpecForcedType.CanReturnFrontal = true;
104     SpecForcedType.CanReturnTail = true;
105     SpecForcedType.CanReturnMid = true;
106 
107     SpecMainType.CanReturnFrontal = true;
108 
109     SpecUnknownExt.CanReturnTail = true; // for sfx
110     SpecUnknownExt.CanReturnMid = true;
111     SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad
112 
113     // ZerosTailIsAllowed = true;
114   }
115 };
116 
117 struct COpenOptions
118 {
119   CCodecs *codecs;
120   COpenType openType;
121   const CObjectVector<COpenType> *types;
122   const CIntVector *excludedFormats;
123 
124   IInStream *stream;
125   ISequentialInStream *seqStream;
126   IArchiveOpenCallback *callback;
127   COpenCallbackImp *callbackSpec; // it's used for SFX only
128   OPEN_PROPS_DECL
129   // bool openOnlySpecifiedByExtension,
130 
131   bool stdInMode;
132   UString filePath;
133 
COpenOptionsCOpenOptions134   COpenOptions():
135       codecs(NULL),
136       types(NULL),
137       excludedFormats(NULL),
138       stream(NULL),
139       seqStream(NULL),
140       callback(NULL),
141       callbackSpec(NULL),
142       stdInMode(false)
143     {}
144 
145 };
146 
147 UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);
148 
149 struct CArcErrorInfo
150 {
151   bool ThereIsTail;
152   bool UnexpecedEnd;
153   bool IgnoreTail; // all are zeros
154   // bool NonZerosTail;
155   bool ErrorFlags_Defined;
156   UInt32 ErrorFlags;
157   UInt32 WarningFlags;
158   int ErrorFormatIndex; // - 1 means no Error.
159                         // if FormatIndex == ErrorFormatIndex, the archive is open with offset
160   UInt64 TailSize;
161 
162   /* if CArc is Open OK with some format:
163         - ErrorFormatIndex shows error format index, if extension is incorrect
164         - other variables show message and warnings of archive that is open */
165 
166   UString ErrorMessage;
167   UString WarningMessage;
168 
169   // call IsArc_After_NonOpen only if Open returns S_FALSE
IsArc_After_NonOpenCArcErrorInfo170   bool IsArc_After_NonOpen() const
171   {
172     return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);
173   }
174 
175 
CArcErrorInfoCArcErrorInfo176   CArcErrorInfo():
177       ThereIsTail(false),
178       UnexpecedEnd(false),
179       IgnoreTail(false),
180       // NonZerosTail(false),
181       ErrorFlags_Defined(false),
182       ErrorFlags(0),
183       WarningFlags(0),
184       ErrorFormatIndex(-1),
185       TailSize(0)
186     {}
187 
188   void ClearErrors();
189 
ClearErrors_FullCArcErrorInfo190   void ClearErrors_Full()
191   {
192     ErrorFormatIndex = -1;
193     ClearErrors();
194   }
195 
IsThereErrorOrWarningCArcErrorInfo196   bool IsThereErrorOrWarning() const
197   {
198     return ErrorFlags != 0
199         || WarningFlags != 0
200         || NeedTailWarning()
201         || UnexpecedEnd
202         || !ErrorMessage.IsEmpty()
203         || !WarningMessage.IsEmpty();
204   }
205 
AreThereErrorsCArcErrorInfo206   bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }
AreThereWarningsCArcErrorInfo207   bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }
208 
NeedTailWarningCArcErrorInfo209   bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; }
210 
GetWarningFlagsCArcErrorInfo211   UInt32 GetWarningFlags() const
212   {
213     UInt32 a = WarningFlags;
214     if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0)
215       a |= kpv_ErrorFlags_DataAfterEnd;
216     return a;
217   }
218 
GetErrorFlagsCArcErrorInfo219   UInt32 GetErrorFlags() const
220   {
221     UInt32 a = ErrorFlags;
222     if (UnexpecedEnd)
223       a |= kpv_ErrorFlags_UnexpectedEnd;
224     return a;
225   }
226 };
227 
228 struct CReadArcItem
229 {
230   UString Path;            // Path from root (including alt stream name, if alt stream)
231   UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode
232 
233   #ifdef SUPPORT_ALT_STREAMS
234   UString MainPath;
235                 /* MainPath = Path for non-AltStream,
236                    MainPath = Path of parent, if there is parent for AltStream. */
237   UString AltStreamName;
238   bool IsAltStream;
239   bool WriteToAltStreamIfColon;
240   #endif
241 
242   bool IsDir;
243   bool MainIsDir;
244   UInt32 ParentIndex; // use it, if IsAltStream
245 
246   #ifndef Z7_SFX
247   bool _use_baseParentFolder_mode;
248   int _baseParentFolder;
249   #endif
250 
CReadArcItemCReadArcItem251   CReadArcItem()
252   {
253     #ifdef SUPPORT_ALT_STREAMS
254     WriteToAltStreamIfColon = false;
255     #endif
256 
257     #ifndef Z7_SFX
258     _use_baseParentFolder_mode = false;
259     _baseParentFolder = -1;
260     #endif
261   }
262 };
263 
264 
265 
266 
267 class CArc
268 {
269   HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);
270   HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);
271   HRESULT OpenStream2(const COpenOptions &options);
272 
273   #ifndef Z7_SFX
274   // parts.Back() can contain alt stream name "nams:AltName"
275   HRESULT GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;
276   #endif
277 
278 public:
279   CMyComPtr<IInArchive> Archive;
280   CMyComPtr<IInStream> InStream;
281           // we use InStream in 2 cases (ArcStreamOffset != 0):
282           // 1) if we use additional cache stream
283           // 2) we reopen sfx archive with CTailInStream
284 
285   CMyComPtr<IArchiveGetRawProps> GetRawProps;
286   CMyComPtr<IArchiveGetRootProps> GetRootProps;
287 
288   bool IsParseArc;
289 
290   bool IsTree;
291   bool IsReadOnly;
292 
293   bool Ask_Deleted;
294   bool Ask_AltStream;
295   bool Ask_Aux;
296   bool Ask_INode;
297 
298   bool IgnoreSplit; // don't try split handler
299 
300   UString Path;
301   UString filePath;
302   UString DefaultName;
303   int FormatIndex;     // -1 means Parser
304   UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile
305 
306   // CFiTime MTime;
307   // bool MTime_Defined;
308   CArcTime MTime;
309 
310   Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler
311   UInt64 PhySize;
312   // UInt64 OkPhySize;
313   bool PhySize_Defined;
314   // bool OkPhySize_Defined;
315   UInt64 FileSize;
316   UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file
317 
318   CArcErrorInfo ErrorInfo; // for OK archives
319   CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)
320 
GetEstmatedPhySize()321   UInt64 GetEstmatedPhySize() const { return PhySize_Defined ? PhySize : FileSize; }
322 
323   UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler
GetGlobalOffset()324   Int64 GetGlobalOffset() const { return (Int64)ArcStreamOffset + Offset; } // it's global offset of archive
325 
326   // AString ErrorFlagsText;
327 
328   // void Set_ErrorFlagsText();
329 
CArc()330   CArc():
331     // MTime_Defined(false),
332     IsTree(false),
333     IsReadOnly(false),
334     Ask_Deleted(false),
335     Ask_AltStream(false),
336     Ask_Aux(false),
337     Ask_INode(false),
338     IgnoreSplit(false)
339     {}
340 
341   HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes);
342 
Close()343   HRESULT Close()
344   {
345     InStream.Release();
346     return Archive->Close();
347   }
348 
349   HRESULT GetItem_Path(UInt32 index, UString &result) const;
350   HRESULT GetItem_DefaultPath(UInt32 index, UString &result) const;
351 
352   // GetItemPath2 adds [DELETED] dir prefix for deleted items.
353   HRESULT GetItem_Path2(UInt32 index, UString &result) const;
354 
355   HRESULT GetItem(UInt32 index, CReadArcItem &item) const;
356 
357   HRESULT GetItem_Size(UInt32 index, UInt64 &size, bool &defined) const;
358 
359   /* if (GetProperty() returns vt==VT_EMPTY), this function sets
360      timestamp from archive file timestamp (MTime).
361      So (at) will be set in most cases (at.Def == true)
362      if (at.Prec == 0)
363      {
364        it means that (Prec == 0) was returned for (kpidMTime),
365        and no value was returned for (kpidTimeType).
366        it can mean Windows precision or unknown precision.
367      }
368   */
369   HRESULT GetItem_MTime(UInt32 index, CArcTime &at) const;
370 
IsItem_Anti(UInt32 index,bool & result)371   HRESULT IsItem_Anti(UInt32 index, bool &result) const
372     { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); }
373 
374 
375   HRESULT OpenStream(const COpenOptions &options);
376   HRESULT OpenStreamOrFile(COpenOptions &options);
377 
378   HRESULT ReOpen(const COpenOptions &options, IArchiveOpenCallback *openCallback_Additional);
379 
380   HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);
381 
IsHashHandler(const COpenOptions & options)382   bool IsHashHandler(const COpenOptions &options) const
383   {
384     if (FormatIndex < 0)
385       return false;
386     return options.codecs->Formats[(unsigned)FormatIndex].Flags_HashHandler();
387   }
388 };
389 
390 struct CArchiveLink
391 {
392   CObjectVector<CArc> Arcs;
393   UStringVector VolumePaths;
394   UInt64 VolumesSize;
395   bool IsOpen;
396 
397   bool PasswordWasAsked;
398   // UString Password;
399 
400   // int NonOpenErrorFormatIndex; // - 1 means no Error.
401   UString NonOpen_ArcPath;
402 
403   CArcErrorInfo NonOpen_ErrorInfo;
404 
405   // UString ErrorsText;
406   // void Set_ErrorsText();
407 
CArchiveLinkCArchiveLink408   CArchiveLink():
409       VolumesSize(0),
410       IsOpen(false),
411       PasswordWasAsked(false)
412       {}
413 
414   void KeepModeForNextOpen();
415   HRESULT Close();
416   void Release();
~CArchiveLinkCArchiveLink417   ~CArchiveLink() { Release(); }
418 
GetArcCArchiveLink419   const CArc *GetArc() const { return &Arcs.Back(); }
GetArchiveCArchiveLink420   IInArchive *GetArchive() const { return Arcs.Back().Archive; }
GetArchiveGetRawPropsCArchiveLink421   IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; }
GetArchiveGetRootPropsCArchiveLink422   IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }
423 
424   /*
425   Open() opens archive and COpenOptions::callback
426   Open2() uses COpenCallbackImp that implements Volumes and password callback
427   Open3() calls Open2() and callbackUI->Open_Finished();
428   Open_Strict() returns S_FALSE also in case, if there is non-open expected nested archive.
429   */
430 
431   HRESULT Open(COpenOptions &options);
432   HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);
433   HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI);
434 
Open_StrictCArchiveLink435   HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI)
436   {
437     HRESULT result = Open3(options, callbackUI);
438     if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
439       result = S_FALSE;
440     return result;
441   }
442 
443   HRESULT ReOpen(COpenOptions &options);
444 };
445 
446 bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);
447 
448 // bool IsHashType(const CObjectVector<COpenType> &types);
449 
450 
451 struct CDirPathSortPair
452 {
453   unsigned Len;
454   unsigned Index;
455 
456   void SetNumSlashes(const FChar *s);
457 
CompareCDirPathSortPair458   int Compare(const CDirPathSortPair &a) const
459   {
460     // We need sorting order where parent items will be after child items
461     if (Len < a.Len) return 1;
462     if (Len > a.Len) return -1;
463     if (Index < a.Index) return -1;
464     if (Index > a.Index) return 1;
465     return 0;
466   }
467 };
468 
469 #endif
470