1 // 7zIn.h 2 3 #ifndef __7Z_IN_H 4 #define __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 _NO_CRYPTO 26 #define _7Z_DECODER_CRYPRO_VARS_DECL 27 #define _7Z_DECODER_CRYPRO_VARS 28 #else 29 #define _7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password 30 #define _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 CBoolVector IsAnti; 119 /* 120 CBoolVector IsAux; 121 CByteBuffer SecureBuf; 122 CRecordVector<UInt32> SecureIDs; 123 */ 124 125 CByteBuffer NamesBuf; 126 CObjArray<size_t> NameOffsets; // numFiles + 1, offsets of utf-16 symbols 127 128 /* 129 void ClearSecure() 130 { 131 SecureBuf.Free(); 132 SecureIDs.Clear(); 133 } 134 */ 135 ClearCDatabase136 void Clear() 137 { 138 CFolders::Clear(); 139 // ClearSecure(); 140 141 NamesBuf.Free(); 142 NameOffsets.Free(); 143 144 Files.Clear(); 145 CTime.Clear(); 146 ATime.Clear(); 147 MTime.Clear(); 148 StartPos.Clear(); 149 IsAnti.Clear(); 150 // IsAux.Clear(); 151 } 152 IsSolidCDatabase153 bool IsSolid() const 154 { 155 for (CNum i = 0; i < NumFolders; i++) 156 if (NumUnpackStreamsVector[i] > 1) 157 return true; 158 return false; 159 } IsItemAntiCDatabase160 bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } 161 // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } 162 163 /* 164 const void* GetName(unsigned index) const 165 { 166 if (!NameOffsets || !NamesBuf) 167 return NULL; 168 return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2); 169 }; 170 */ 171 void GetPath(unsigned index, UString &path) const; 172 HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw(); 173 }; 174 175 struct CInArchiveInfo 176 { 177 CArchiveVersion Version; 178 UInt64 StartPosition; 179 UInt64 StartPositionAfterHeader; 180 UInt64 DataStartPosition; 181 UInt64 DataStartPosition2; 182 CRecordVector<UInt64> FileInfoPopIDs; 183 ClearCInArchiveInfo184 void Clear() 185 { 186 StartPosition = 0; 187 StartPositionAfterHeader = 0; 188 DataStartPosition = 0; 189 DataStartPosition2 = 0; 190 FileInfoPopIDs.Clear(); 191 } 192 }; 193 194 struct CDbEx: public CDatabase 195 { 196 CInArchiveInfo ArcInfo; 197 198 CObjArray<CNum> FolderStartFileIndex; 199 CObjArray<CNum> FileIndexToFolderIndexMap; 200 201 UInt64 HeadersSize; 202 UInt64 PhySize; 203 204 /* 205 CRecordVector<size_t> SecureOffsets; 206 bool IsTree; 207 bool ThereAreAltStreams; 208 */ 209 210 bool IsArc; 211 bool PhySizeWasConfirmed; 212 213 bool ThereIsHeaderError; 214 bool UnexpectedEnd; 215 // bool UnsupportedVersion; 216 217 bool StartHeaderWasRecovered; 218 bool UnsupportedFeatureWarning; 219 bool UnsupportedFeatureError; 220 221 /* 222 void ClearSecureEx() 223 { 224 ClearSecure(); 225 SecureOffsets.Clear(); 226 } 227 */ 228 ClearCDbEx229 void Clear() 230 { 231 IsArc = false; 232 PhySizeWasConfirmed = false; 233 234 ThereIsHeaderError = false; 235 UnexpectedEnd = false; 236 // UnsupportedVersion = false; 237 238 StartHeaderWasRecovered = false; 239 UnsupportedFeatureError = false; 240 UnsupportedFeatureWarning = false; 241 242 /* 243 IsTree = false; 244 ThereAreAltStreams = false; 245 */ 246 247 CDatabase::Clear(); 248 249 // SecureOffsets.Clear(); 250 ArcInfo.Clear(); 251 FolderStartFileIndex.Free(); 252 FileIndexToFolderIndexMap.Free(); 253 254 HeadersSize = 0; 255 PhySize = 0; 256 } 257 258 void FillLinks(); 259 GetFolderStreamPosCDbEx260 UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const 261 { 262 return ArcInfo.DataStartPosition + 263 PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; 264 } 265 GetFolderFullPackSizeCDbEx266 UInt64 GetFolderFullPackSize(CNum folderIndex) const 267 { 268 return 269 PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - 270 PackPositions[FoStartPackStreamIndex[folderIndex]]; 271 } 272 GetFolderPackStreamSizeCDbEx273 UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const 274 { 275 size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex; 276 return PackPositions[i + 1] - PackPositions[i]; 277 } 278 GetFilePackSizeCDbEx279 UInt64 GetFilePackSize(CNum fileIndex) const 280 { 281 CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; 282 if (folderIndex != kNumNoIndex) 283 if (FolderStartFileIndex[folderIndex] == fileIndex) 284 return GetFolderFullPackSize(folderIndex); 285 return 0; 286 } 287 }; 288 289 const unsigned kNumBufLevelsMax = 4; 290 291 struct CInByte2 292 { 293 const Byte *_buffer; 294 public: 295 size_t _size; 296 size_t _pos; 297 GetRemCInByte2298 size_t GetRem() const { return _size - _pos; } GetPtrCInByte2299 const Byte *GetPtr() const { return _buffer + _pos; } InitCInByte2300 void Init(const Byte *buffer, size_t size) 301 { 302 _buffer = buffer; 303 _size = size; 304 _pos = 0; 305 } 306 Byte ReadByte(); 307 void ReadBytes(Byte *data, size_t size); SkipDataNoCheckCInByte2308 void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; } 309 void SkipData(UInt64 size); 310 311 void SkipData(); SkipRemCInByte2312 void SkipRem() { _pos = _size; } 313 UInt64 ReadNumber(); 314 CNum ReadNum(); 315 UInt32 ReadUInt32(); 316 UInt64 ReadUInt64(); 317 318 void ParseFolder(CFolder &folder); 319 }; 320 321 class CStreamSwitch; 322 323 const UInt32 kHeaderSize = 32; 324 325 class CInArchive 326 { 327 friend class CStreamSwitch; 328 329 CMyComPtr<IInStream> _stream; 330 331 unsigned _numInByteBufs; 332 CInByte2 _inByteVector[kNumBufLevelsMax]; 333 334 CInByte2 *_inByteBack; 335 bool ThereIsHeaderError; 336 337 UInt64 _arhiveBeginStreamPosition; 338 UInt64 _fileEndPosition; 339 340 Byte _header[kHeaderSize]; 341 342 UInt64 HeadersSize; 343 344 bool _useMixerMT; 345 346 void AddByteStream(const Byte *buffer, size_t size); 347 DeleteByteStream(bool needUpdatePos)348 void DeleteByteStream(bool needUpdatePos) 349 { 350 _numInByteBufs--; 351 if (_numInByteBufs > 0) 352 { 353 _inByteBack = &_inByteVector[_numInByteBufs - 1]; 354 if (needUpdatePos) 355 _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos; 356 } 357 } 358 359 HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); 360 ReadBytes(Byte * data,size_t size)361 void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } ReadByte()362 Byte ReadByte() { return _inByteBack->ReadByte(); } ReadNumber()363 UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } ReadNum()364 CNum ReadNum() { return _inByteBack->ReadNum(); } ReadID()365 UInt64 ReadID() { return _inByteBack->ReadNumber(); } ReadUInt32()366 UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } ReadUInt64()367 UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } SkipData(UInt64 size)368 void SkipData(UInt64 size) { _inByteBack->SkipData(size); } SkipData()369 void SkipData() { _inByteBack->SkipData(); } 370 void WaitId(UInt64 id); 371 372 void ReadArchiveProperties(CInArchiveInfo &archiveInfo); 373 void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs); 374 375 void ReadPackInfo(CFolders &f); 376 377 void ReadUnpackInfo( 378 const CObjectVector<CByteBuffer> *dataVector, 379 CFolders &folders); 380 381 void ReadSubStreamsInfo( 382 CFolders &folders, 383 CRecordVector<UInt64> &unpackSizes, 384 CUInt32DefVector &digests); 385 386 void ReadStreamsInfo( 387 const CObjectVector<CByteBuffer> *dataVector, 388 UInt64 &dataOffset, 389 CFolders &folders, 390 CRecordVector<UInt64> &unpackSizes, 391 CUInt32DefVector &digests); 392 393 void ReadBoolVector(unsigned numItems, CBoolVector &v); 394 void ReadBoolVector2(unsigned numItems, CBoolVector &v); 395 void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, 396 CUInt64DefVector &v, unsigned numItems); 397 HRESULT ReadAndDecodePackedStreams( 398 DECL_EXTERNAL_CODECS_LOC_VARS 399 UInt64 baseOffset, UInt64 &dataOffset, 400 CObjectVector<CByteBuffer> &dataVector 401 _7Z_DECODER_CRYPRO_VARS_DECL 402 ); 403 HRESULT ReadHeader( 404 DECL_EXTERNAL_CODECS_LOC_VARS 405 CDbEx &db 406 _7Z_DECODER_CRYPRO_VARS_DECL 407 ); 408 HRESULT ReadDatabase2( 409 DECL_EXTERNAL_CODECS_LOC_VARS 410 CDbEx &db 411 _7Z_DECODER_CRYPRO_VARS_DECL 412 ); 413 public: CInArchive(bool useMixerMT)414 CInArchive(bool useMixerMT): 415 _numInByteBufs(0), 416 _useMixerMT(useMixerMT) 417 {} 418 419 HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive 420 void Close(); 421 422 HRESULT ReadDatabase( 423 DECL_EXTERNAL_CODECS_LOC_VARS 424 CDbEx &db 425 _7Z_DECODER_CRYPRO_VARS_DECL 426 ); 427 }; 428 429 }} 430 431 #endif 432