1 // Rar5Handler.h 2 3 #ifndef __RAR5_HANDLER_H 4 #define __RAR5_HANDLER_H 5 6 #include "../../../../C/Blake2.h" 7 8 #include "../../../Common/MyBuffer.h" 9 10 #include "../../../Windows/PropVariant.h" 11 12 #include "../../Common/CreateCoder.h" 13 14 #include "../IArchive.h" 15 16 namespace NArchive { 17 namespace NRar5 { 18 19 namespace NHeaderFlags 20 { 21 const unsigned kExtra = 1 << 0; 22 const unsigned kData = 1 << 1; 23 // const unsigned kUnknown = 1 << 2; 24 const unsigned kPrevVol = 1 << 3; 25 const unsigned kNextVol = 1 << 4; 26 // const unsigned kIsChild = 1 << 5; 27 // const unsigned kPreserveChild = 1 << 6; 28 } 29 30 namespace NHeaderType 31 { 32 enum 33 { 34 kArc = 1, 35 kFile, 36 kService, 37 kArcEncrypt, 38 kEndOfArc 39 }; 40 } 41 42 namespace NArcFlags 43 { 44 const unsigned kVol = 1 << 0; 45 const unsigned kVolNumber = 1 << 1; 46 const unsigned kSolid = 1 << 2; 47 // const unsigned kRecovery = 1 << 3; 48 // const unsigned kLocked = 1 << 4; 49 } 50 51 const unsigned kArcExtraRecordType_Locator = 1; 52 53 namespace NLocatorFlags 54 { 55 const unsigned kQuickOpen = 1 << 0; 56 const unsigned kRecovery = 1 << 1; 57 } 58 59 namespace NFileFlags 60 { 61 const unsigned kIsDir = 1 << 0; 62 const unsigned kUnixTime = 1 << 1; 63 const unsigned kCrc32 = 1 << 2; 64 const unsigned kUnknownSize = 1 << 3; 65 } 66 67 namespace NMethodFlags 68 { 69 // const unsigned kVersionMask = 0x3F; 70 const unsigned kSolid = 1 << 6; 71 } 72 73 namespace NArcEndFlags 74 { 75 const unsigned kMoreVols = 1 << 0; 76 } 77 78 enum EHostOS 79 { 80 kHost_Windows = 0, 81 kHost_Unix 82 }; 83 84 85 86 // ---------- Extra ---------- 87 88 namespace NExtraID 89 { 90 enum 91 { 92 kCrypto = 1, 93 kHash, 94 kTime, 95 kVersion, 96 kLink, 97 kUnixOwner, 98 kSubdata 99 }; 100 } 101 102 const unsigned kCryptoAlgo_AES = 0; 103 104 namespace NCryptoFlags 105 { 106 const unsigned kPswCheck = 1 << 0; 107 const unsigned kUseMAC = 1 << 1; 108 } 109 110 struct CCryptoInfo 111 { 112 UInt64 Algo; 113 UInt64 Flags; 114 Byte Cnt; 115 UseMACCCryptoInfo116 bool UseMAC() const { return (Flags & NCryptoFlags::kUseMAC) != 0; } IsThereCheckCCryptoInfo117 bool IsThereCheck() const { return (Flags & NCryptoFlags::kPswCheck) != 0; } 118 bool Parse(const Byte *p, size_t size); 119 }; 120 121 const unsigned kHashID_Blake2sp = 0; 122 123 namespace NTimeRecord 124 { 125 enum 126 { 127 k_Index_MTime = 0, 128 k_Index_CTime, 129 k_Index_ATime 130 }; 131 132 namespace NFlags 133 { 134 const unsigned kUnixTime = 1 << 0; 135 const unsigned kMTime = 1 << 1; 136 const unsigned kCTime = 1 << 2; 137 const unsigned kATime = 1 << 3; 138 const unsigned kUnixNs = 1 << 4; 139 } 140 } 141 142 namespace NLinkType 143 { 144 enum 145 { 146 kUnixSymLink = 1, 147 kWinSymLink, 148 kWinJunction, 149 kHardLink, 150 kFileCopy 151 }; 152 } 153 154 namespace NLinkFlags 155 { 156 const unsigned kTargetIsDir = 1 << 0; 157 } 158 159 160 struct CLinkInfo 161 { 162 UInt64 Type; 163 UInt64 Flags; 164 unsigned NameOffset; 165 unsigned NameLen; 166 167 bool Parse(const Byte *p, unsigned size); 168 }; 169 170 171 struct CItem 172 { 173 UInt32 CommonFlags; 174 UInt32 Flags; 175 176 Byte RecordType; 177 bool Version_Defined; 178 179 int ACL; 180 181 AString Name; 182 183 int VolIndex; 184 int NextItem; 185 186 UInt32 UnixMTime; 187 UInt32 CRC; 188 UInt32 Attrib; 189 UInt32 Method; 190 191 CByteBuffer Extra; 192 193 UInt64 Size; 194 UInt64 PackSize; 195 UInt64 HostOS; 196 197 UInt64 DataPos; 198 UInt64 Version; 199 CItemCItem200 CItem() { Clear(); } 201 ClearCItem202 void Clear() 203 { 204 CommonFlags = 0; 205 Flags = 0; 206 207 VolIndex = 0; 208 NextItem = -1; 209 210 Version_Defined = false; 211 Version = 0; 212 213 Name.Empty(); 214 Extra.Free(); 215 ACL = -1; 216 } 217 IsSplitBeforeCItem218 bool IsSplitBefore() const { return (CommonFlags & NHeaderFlags::kPrevVol) != 0; } IsSplitAfterCItem219 bool IsSplitAfter() const { return (CommonFlags & NHeaderFlags::kNextVol) != 0; } IsSplitCItem220 bool IsSplit() const { return (CommonFlags & (NHeaderFlags::kPrevVol | NHeaderFlags::kNextVol)) != 0; } 221 IsDirCItem222 bool IsDir() const { return (Flags & NFileFlags::kIsDir) != 0; } Has_UnixMTimeCItem223 bool Has_UnixMTime() const { return (Flags & NFileFlags::kUnixTime) != 0; } Has_CRCCItem224 bool Has_CRC() const { return (Flags & NFileFlags::kCrc32) != 0; } Is_UnknownSizeCItem225 bool Is_UnknownSize() const { return (Flags & NFileFlags::kUnknownSize) != 0; } 226 IsNextForItemCItem227 bool IsNextForItem(const CItem &prev) const 228 { 229 return !IsDir() && !prev.IsDir() && IsSplitBefore() && prev.IsSplitAfter() && (Name == prev.Name); 230 // && false; 231 } 232 IsSolidCItem233 bool IsSolid() const { return ((UInt32)Method & NMethodFlags::kSolid) != 0; } GetAlgoVersionCItem234 unsigned GetAlgoVersion() const { return (unsigned)Method & 0x3F; } GetMethodCItem235 unsigned GetMethod() const { return ((unsigned)Method >> 7) & 0x7; } GetDictSizeCItem236 UInt32 GetDictSize() const { return (((UInt32)Method >> 10) & 0xF); } 237 IsServiceCItem238 bool IsService() const { return RecordType == NHeaderType::kService; } 239 Is_STMCItem240 bool Is_STM() const { return IsService() && Name == "STM"; } Is_CMTCItem241 bool Is_CMT() const { return IsService() && Name == "CMT"; } Is_ACLCItem242 bool Is_ACL() const { return IsService() && Name == "ACL"; } 243 // bool Is_QO() const { return IsService() && Name == "QO"; } 244 245 int FindExtra(unsigned extraID, unsigned &recordDataSize) const; 246 void PrintInfo(AString &s) const; 247 248 IsEncryptedCItem249 bool IsEncrypted() const 250 { 251 unsigned size; 252 return FindExtra(NExtraID::kCrypto, size) >= 0; 253 } 254 FindExtra_BlakeCItem255 int FindExtra_Blake() const 256 { 257 unsigned size = 0; 258 int offset = FindExtra(NExtraID::kHash, size); 259 if (offset >= 0 260 && size == BLAKE2S_DIGEST_SIZE + 1 261 && Extra[(unsigned)offset] == kHashID_Blake2sp) 262 return offset + 1; 263 return -1; 264 } 265 266 bool FindExtra_Version(UInt64 &version) const; 267 268 bool FindExtra_Link(CLinkInfo &link) const; 269 void Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const; 270 bool Is_CopyLink() const; 271 bool Is_HardLink() const; 272 bool Is_CopyLink_or_HardLink() const; 273 NeedUse_as_CopyLinkCItem274 bool NeedUse_as_CopyLink() const { return PackSize == 0 && Is_CopyLink(); } NeedUse_as_HardLinkCItem275 bool NeedUse_as_HardLink() const { return PackSize == 0 && Is_HardLink(); } NeedUse_as_CopyLink_or_HardLinkCItem276 bool NeedUse_as_CopyLink_or_HardLink() const { return PackSize == 0 && Is_CopyLink_or_HardLink(); } 277 278 bool GetAltStreamName(AString &name) const; 279 GetWinAttribCItem280 UInt32 GetWinAttrib() const 281 { 282 UInt32 a; 283 switch (HostOS) 284 { 285 case kHost_Windows: a = Attrib; break; 286 case kHost_Unix: a = (Attrib << 16); break; 287 default: a = 0; 288 } 289 // if (IsDir()) a |= FILE_ATTRIBUTE_DIRECTORY; 290 return a; 291 } 292 GetDataPositionCItem293 UInt64 GetDataPosition() const { return DataPos; } 294 }; 295 296 297 struct CInArcInfo 298 { 299 UInt64 Flags; 300 UInt64 VolNumber; 301 UInt64 StartPos; 302 UInt64 EndPos; 303 304 UInt64 EndFlags; 305 bool EndOfArchive_was_Read; 306 307 bool IsEncrypted; 308 309 // CByteBuffer Extra; 310 311 /* 312 struct CLocator 313 { 314 UInt64 Flags; 315 UInt64 QuickOpen; 316 UInt64 Recovery; 317 318 bool Is_QuickOpen() const { return (Flags & NLocatorFlags::kQuickOpen) != 0; } 319 bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; } 320 }; 321 322 int FindExtra(unsigned extraID, unsigned &recordDataSize) const; 323 bool FindExtra_Locator(CLocator &locator) const; 324 */ 325 CInArcInfoCInArcInfo326 CInArcInfo(): 327 Flags(0), 328 VolNumber(0), 329 StartPos(0), 330 EndPos(0), 331 EndFlags(0), 332 EndOfArchive_was_Read(false), 333 IsEncrypted(false) 334 {} 335 336 /* 337 void Clear() 338 { 339 Flags = 0; 340 VolNumber = 0; 341 StartPos = 0; 342 EndPos = 0; 343 EndFlags = 0; 344 EndOfArchive_was_Read = false; 345 Extra.Free(); 346 } 347 */ 348 GetPhySizeCInArcInfo349 UInt64 GetPhySize() const { return EndPos - StartPos; } 350 AreMoreVolumesCInArcInfo351 bool AreMoreVolumes() const { return (EndFlags & NArcEndFlags::kMoreVols) != 0; } 352 IsVolumeCInArcInfo353 bool IsVolume() const { return (Flags & NArcFlags::kVol) != 0; } IsSolidCInArcInfo354 bool IsSolid() const { return (Flags & NArcFlags::kSolid) != 0; } Is_VolNumber_DefinedCInArcInfo355 bool Is_VolNumber_Defined() const { return (Flags & NArcFlags::kVolNumber) != 0; } 356 GetVolIndexCInArcInfo357 UInt64 GetVolIndex() const { return Is_VolNumber_Defined() ? VolNumber : 0; } 358 }; 359 360 361 struct CRefItem 362 { 363 unsigned Item; 364 unsigned Last; 365 int Parent; 366 int Link; 367 }; 368 369 370 struct CArc 371 { 372 CMyComPtr<IInStream> Stream; 373 CInArcInfo Info; 374 }; 375 376 377 class CHandler: 378 public IInArchive, 379 public IArchiveGetRawProps, 380 PUBLIC_ISetCompressCodecsInfo 381 public CMyUnknownImp 382 { 383 public: 384 CRecordVector<CRefItem> _refs; 385 CObjectVector<CItem> _items; 386 private: 387 CObjectVector<CArc> _arcs; 388 CObjectVector<CByteBuffer> _acls; 389 390 UInt32 _errorFlags; 391 // UInt32 _warningFlags; 392 bool _isArc; 393 CByteBuffer _comment; 394 UString _missingVolName; 395 396 DECL_EXTERNAL_CODECS_VARS 397 398 UInt64 GetPackSize(unsigned refIndex) const; 399 400 void FillLinks(); 401 402 HRESULT Open2(IInStream *stream, 403 const UInt64 *maxCheckStartPosition, 404 IArchiveOpenCallback *openCallback); 405 406 public: 407 MY_QUERYINTERFACE_BEGIN2(IInArchive) 408 MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps) 409 QUERY_ENTRY_ISetCompressCodecsInfo 410 MY_QUERYINTERFACE_END 411 MY_ADDREF_RELEASE 412 413 INTERFACE_IInArchive(;) 414 INTERFACE_IArchiveGetRawProps(;) 415 416 DECL_ISetCompressCodecsInfo 417 }; 418 419 }} 420 421 #endif 422