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