1 // 7zIn.h 2 3 #ifndef ZIP7_INC_7Z_IN_H 4 #define ZIP7_INC_7Z_IN_H 5 6 #include "../../../Common/MyCom.h" 7 8 #include "../../../Windows/PropVariant.h" 9 10 #include "../../IPassword.h" 11 #include "../../IStream.h" 12 13 #include "../../Common/CreateCoder.h" 14 #include "../../Common/InBuffer.h" 15 16 #include "7zItem.h" 17 18 namespace NArchive { 19 namespace N7z { 20 21 /* 22 We don't need to init isEncrypted and passwordIsDefined 23 We must upgrade them only */ 24 25 #ifdef Z7_NO_CRYPTO 26 #define Z7_7Z_DECODER_CRYPRO_VARS_DECL 27 #define Z7_7Z_DECODER_CRYPRO_VARS 28 #else 29 #define Z7_7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password 30 #define Z7_7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password 31 #endif 32 33 struct CParsedMethods 34 { 35 Byte Lzma2Prop; 36 UInt32 LzmaDic; 37 CRecordVector<UInt64> IDs; 38 CParsedMethodsCParsedMethods39 CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {} 40 }; 41 42 struct CFolderEx: public CFolder 43 { 44 unsigned UnpackCoder; 45 }; 46 47 struct CFolders 48 { 49 CNum NumPackStreams; 50 CNum NumFolders; 51 52 CObjArray<UInt64> PackPositions; // NumPackStreams + 1 53 // CUInt32DefVector PackCRCs; // we don't use PackCRCs now 54 55 CUInt32DefVector FolderCRCs; // NumFolders 56 CObjArray<CNum> NumUnpackStreamsVector; // NumFolders 57 58 CObjArray<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders 59 CObjArray<CNum> FoToCoderUnpackSizes; // NumFolders + 1 60 CObjArray<CNum> FoStartPackStreamIndex; // NumFolders + 1 61 CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders 62 63 CObjArray<size_t> FoCodersDataOffset; // NumFolders + 1 64 CByteBuffer CodersData; 65 66 CParsedMethods ParsedMethods; 67 68 void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const; ParseFolderExCFolders69 void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const 70 { 71 ParseFolderInfo(folderIndex, folder); 72 folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex]; 73 } 74 GetNumFolderUnpackSizesCFolders75 unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const 76 { 77 return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]); 78 } 79 GetFolderUnpackSizeCFolders80 UInt64 GetFolderUnpackSize(unsigned folderIndex) const 81 { 82 return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]]; 83 } 84 GetStreamPackSizeCFolders85 UInt64 GetStreamPackSize(unsigned index) const 86 { 87 return PackPositions[index + 1] - PackPositions[index]; 88 } 89 CFoldersCFolders90 CFolders(): NumPackStreams(0), NumFolders(0) {} 91 ClearCFolders92 void Clear() 93 { 94 NumPackStreams = 0; 95 PackPositions.Free(); 96 // PackCRCs.Clear(); 97 98 NumFolders = 0; 99 FolderCRCs.Clear(); 100 NumUnpackStreamsVector.Free(); 101 CoderUnpackSizes.Free(); 102 FoToCoderUnpackSizes.Free(); 103 FoStartPackStreamIndex.Free(); 104 FoToMainUnpackSizeIndex.Free(); 105 FoCodersDataOffset.Free(); 106 CodersData.Free(); 107 } 108 }; 109 110 struct CDatabase: public CFolders 111 { 112 CRecordVector<CFileItem> Files; 113 114 CUInt64DefVector CTime; 115 CUInt64DefVector ATime; 116 CUInt64DefVector MTime; 117 CUInt64DefVector StartPos; 118 CUInt32DefVector Attrib; 119 CBoolVector IsAnti; 120 /* 121 CBoolVector IsAux; 122 CByteBuffer SecureBuf; 123 CRecordVector<UInt32> SecureIDs; 124 */ 125 126 CByteBuffer NamesBuf; 127 CObjArray<size_t> NameOffsets; // numFiles + 1, offsets of utf-16 symbols 128 129 /* 130 void ClearSecure() 131 { 132 SecureBuf.Free(); 133 SecureIDs.Clear(); 134 } 135 */ 136 ClearCDatabase137 void Clear() 138 { 139 CFolders::Clear(); 140 // ClearSecure(); 141 142 NamesBuf.Free(); 143 NameOffsets.Free(); 144 145 Files.Clear(); 146 CTime.Clear(); 147 ATime.Clear(); 148 MTime.Clear(); 149 StartPos.Clear(); 150 Attrib.Clear(); 151 IsAnti.Clear(); 152 // IsAux.Clear(); 153 } 154 IsSolidCDatabase155 bool IsSolid() const 156 { 157 for (CNum i = 0; i < NumFolders; i++) 158 if (NumUnpackStreamsVector[i] > 1) 159 return true; 160 return false; 161 } IsItemAntiCDatabase162 bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } 163 // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } 164 165 /* 166 const void* GetName(unsigned index) const 167 { 168 if (!NameOffsets || !NamesBuf) 169 return NULL; 170 return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2); 171 }; 172 */ 173 void GetPath(unsigned index, UString &path) const; 174 HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw(); 175 }; 176 177 178 struct CInArchiveInfo 179 { 180 CArchiveVersion Version; 181 UInt64 StartPosition; // in stream 182 UInt64 StartPositionAfterHeader; // in stream 183 UInt64 DataStartPosition; // in stream 184 UInt64 DataStartPosition2; // in stream. it's for headers 185 CRecordVector<UInt64> FileInfoPopIDs; 186 ClearCInArchiveInfo187 void Clear() 188 { 189 StartPosition = 0; 190 StartPositionAfterHeader = 0; 191 DataStartPosition = 0; 192 DataStartPosition2 = 0; 193 FileInfoPopIDs.Clear(); 194 } 195 }; 196 197 198 struct CDbEx: public CDatabase 199 { 200 CInArchiveInfo ArcInfo; 201 202 CObjArray<CNum> FolderStartFileIndex; 203 CObjArray<CNum> FileIndexToFolderIndexMap; 204 205 UInt64 HeadersSize; 206 UInt64 PhySize; 207 // UInt64 EndHeaderOffset; // relative to position after StartHeader (32 bytes) 208 209 /* 210 CRecordVector<size_t> SecureOffsets; 211 bool IsTree; 212 bool ThereAreAltStreams; 213 */ 214 215 bool IsArc; 216 bool PhySizeWasConfirmed; 217 218 bool ThereIsHeaderError; 219 bool UnexpectedEnd; 220 // bool UnsupportedVersion; 221 222 bool StartHeaderWasRecovered; 223 bool UnsupportedFeatureWarning; 224 bool UnsupportedFeatureError; 225 226 /* 227 void ClearSecureEx() 228 { 229 ClearSecure(); 230 SecureOffsets.Clear(); 231 } 232 */ 233 ClearCDbEx234 void Clear() 235 { 236 IsArc = false; 237 PhySizeWasConfirmed = false; 238 239 ThereIsHeaderError = false; 240 UnexpectedEnd = false; 241 // UnsupportedVersion = false; 242 243 StartHeaderWasRecovered = false; 244 UnsupportedFeatureError = false; 245 UnsupportedFeatureWarning = false; 246 247 /* 248 IsTree = false; 249 ThereAreAltStreams = false; 250 */ 251 252 CDatabase::Clear(); 253 254 // SecureOffsets.Clear(); 255 ArcInfo.Clear(); 256 FolderStartFileIndex.Free(); 257 FileIndexToFolderIndexMap.Free(); 258 259 HeadersSize = 0; 260 PhySize = 0; 261 // EndHeaderOffset = 0; 262 } 263 CanUpdateCDbEx264 bool CanUpdate() const 265 { 266 if (ThereIsHeaderError 267 || UnexpectedEnd 268 || StartHeaderWasRecovered 269 || UnsupportedFeatureError) 270 return false; 271 return true; 272 } 273 274 void FillLinks(); 275 GetFolderStreamPosCDbEx276 UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const 277 { 278 return ArcInfo.DataStartPosition + 279 PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; 280 } 281 GetFolderFullPackSizeCDbEx282 UInt64 GetFolderFullPackSize(CNum folderIndex) const 283 { 284 return 285 PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - 286 PackPositions[FoStartPackStreamIndex[folderIndex]]; 287 } 288 GetFolderPackStreamSizeCDbEx289 UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const 290 { 291 size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex; 292 return PackPositions[i + 1] - PackPositions[i]; 293 } 294 GetFilePackSizeCDbEx295 UInt64 GetFilePackSize(CNum fileIndex) const 296 { 297 CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; 298 if (folderIndex != kNumNoIndex) 299 if (FolderStartFileIndex[folderIndex] == fileIndex) 300 return GetFolderFullPackSize(folderIndex); 301 return 0; 302 } 303 }; 304 305 const unsigned kNumBufLevelsMax = 4; 306 307 struct CInByte2 308 { 309 const Byte *_buffer; 310 public: 311 size_t _size; 312 size_t _pos; 313 GetRemCInByte2314 size_t GetRem() const { return _size - _pos; } GetPtrCInByte2315 const Byte *GetPtr() const { return _buffer + _pos; } InitCInByte2316 void Init(const Byte *buffer, size_t size) 317 { 318 _buffer = buffer; 319 _size = size; 320 _pos = 0; 321 } 322 Byte ReadByte(); 323 void ReadBytes(Byte *data, size_t size); SkipDataNoCheckCInByte2324 void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; } 325 void SkipData(UInt64 size); 326 327 void SkipData(); SkipRemCInByte2328 void SkipRem() { _pos = _size; } 329 UInt64 ReadNumber(); 330 CNum ReadNum(); 331 UInt32 ReadUInt32(); 332 UInt64 ReadUInt64(); 333 334 void ParseFolder(CFolder &folder); 335 }; 336 337 class CStreamSwitch; 338 339 const UInt32 kHeaderSize = 32; 340 341 class CInArchive 342 { 343 friend class CStreamSwitch; 344 345 CMyComPtr<IInStream> _stream; 346 347 unsigned _numInByteBufs; 348 CInByte2 _inByteVector[kNumBufLevelsMax]; 349 350 CInByte2 *_inByteBack; 351 bool ThereIsHeaderError; 352 353 UInt64 _arhiveBeginStreamPosition; 354 UInt64 _fileEndPosition; 355 356 UInt64 _rangeLimit; // relative to position after StartHeader (32 bytes) 357 358 Byte _header[kHeaderSize]; 359 360 UInt64 HeadersSize; 361 362 bool _useMixerMT; 363 364 void AddByteStream(const Byte *buffer, size_t size); 365 DeleteByteStream(bool needUpdatePos)366 void DeleteByteStream(bool needUpdatePos) 367 { 368 _numInByteBufs--; 369 if (_numInByteBufs > 0) 370 { 371 _inByteBack = &_inByteVector[_numInByteBufs - 1]; 372 if (needUpdatePos) 373 _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos; 374 } 375 } 376 377 HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); 378 ReadBytes(Byte * data,size_t size)379 void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } ReadByte()380 Byte ReadByte() { return _inByteBack->ReadByte(); } ReadNumber()381 UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } ReadNum()382 CNum ReadNum() { return _inByteBack->ReadNum(); } ReadID()383 UInt64 ReadID() { return _inByteBack->ReadNumber(); } ReadUInt32()384 UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } ReadUInt64()385 UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } SkipData(UInt64 size)386 void SkipData(UInt64 size) { _inByteBack->SkipData(size); } SkipData()387 void SkipData() { _inByteBack->SkipData(); } 388 void WaitId(UInt64 id); 389 390 void Read_UInt32_Vector(CUInt32DefVector &v); 391 392 void ReadArchiveProperties(CInArchiveInfo &archiveInfo); 393 void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs); 394 395 void ReadPackInfo(CFolders &f); 396 397 void ReadUnpackInfo( 398 const CObjectVector<CByteBuffer> *dataVector, 399 CFolders &folders); 400 401 void ReadSubStreamsInfo( 402 CFolders &folders, 403 CRecordVector<UInt64> &unpackSizes, 404 CUInt32DefVector &digests); 405 406 void ReadStreamsInfo( 407 const CObjectVector<CByteBuffer> *dataVector, 408 UInt64 &dataOffset, 409 CFolders &folders, 410 CRecordVector<UInt64> &unpackSizes, 411 CUInt32DefVector &digests); 412 413 void ReadBoolVector(unsigned numItems, CBoolVector &v); 414 void ReadBoolVector2(unsigned numItems, CBoolVector &v); 415 void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, 416 CUInt64DefVector &v, unsigned numItems); 417 HRESULT ReadAndDecodePackedStreams( 418 DECL_EXTERNAL_CODECS_LOC_VARS 419 UInt64 baseOffset, UInt64 &dataOffset, 420 CObjectVector<CByteBuffer> &dataVector 421 Z7_7Z_DECODER_CRYPRO_VARS_DECL 422 ); 423 HRESULT ReadHeader( 424 DECL_EXTERNAL_CODECS_LOC_VARS 425 CDbEx &db 426 Z7_7Z_DECODER_CRYPRO_VARS_DECL 427 ); 428 HRESULT ReadDatabase2( 429 DECL_EXTERNAL_CODECS_LOC_VARS 430 CDbEx &db 431 Z7_7Z_DECODER_CRYPRO_VARS_DECL 432 ); 433 public: CInArchive(bool useMixerMT)434 CInArchive(bool useMixerMT): 435 _numInByteBufs(0), 436 _useMixerMT(useMixerMT) 437 {} 438 439 HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive 440 void Close(); 441 442 HRESULT ReadDatabase( 443 DECL_EXTERNAL_CODECS_LOC_VARS 444 CDbEx &db 445 Z7_7Z_DECODER_CRYPRO_VARS_DECL 446 ); 447 }; 448 449 }} 450 451 #endif 452