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 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 struct CInArchiveInfo 178 { 179 CArchiveVersion Version; 180 UInt64 StartPosition; 181 UInt64 StartPositionAfterHeader; 182 UInt64 DataStartPosition; 183 UInt64 DataStartPosition2; 184 CRecordVector<UInt64> FileInfoPopIDs; 185 ClearCInArchiveInfo186 void Clear() 187 { 188 StartPosition = 0; 189 StartPositionAfterHeader = 0; 190 DataStartPosition = 0; 191 DataStartPosition2 = 0; 192 FileInfoPopIDs.Clear(); 193 } 194 }; 195 196 struct CDbEx: public CDatabase 197 { 198 CInArchiveInfo ArcInfo; 199 200 CObjArray<CNum> FolderStartFileIndex; 201 CObjArray<CNum> FileIndexToFolderIndexMap; 202 203 UInt64 HeadersSize; 204 UInt64 PhySize; 205 206 /* 207 CRecordVector<size_t> SecureOffsets; 208 bool IsTree; 209 bool ThereAreAltStreams; 210 */ 211 212 bool IsArc; 213 bool PhySizeWasConfirmed; 214 215 bool ThereIsHeaderError; 216 bool UnexpectedEnd; 217 // bool UnsupportedVersion; 218 219 bool StartHeaderWasRecovered; 220 bool UnsupportedFeatureWarning; 221 bool UnsupportedFeatureError; 222 223 /* 224 void ClearSecureEx() 225 { 226 ClearSecure(); 227 SecureOffsets.Clear(); 228 } 229 */ 230 ClearCDbEx231 void Clear() 232 { 233 IsArc = false; 234 PhySizeWasConfirmed = false; 235 236 ThereIsHeaderError = false; 237 UnexpectedEnd = false; 238 // UnsupportedVersion = false; 239 240 StartHeaderWasRecovered = false; 241 UnsupportedFeatureError = false; 242 UnsupportedFeatureWarning = false; 243 244 /* 245 IsTree = false; 246 ThereAreAltStreams = false; 247 */ 248 249 CDatabase::Clear(); 250 251 // SecureOffsets.Clear(); 252 ArcInfo.Clear(); 253 FolderStartFileIndex.Free(); 254 FileIndexToFolderIndexMap.Free(); 255 256 HeadersSize = 0; 257 PhySize = 0; 258 } 259 CanUpdateCDbEx260 bool CanUpdate() const 261 { 262 if (ThereIsHeaderError 263 || UnexpectedEnd 264 || StartHeaderWasRecovered 265 || UnsupportedFeatureError) 266 return false; 267 return true; 268 } 269 270 void FillLinks(); 271 GetFolderStreamPosCDbEx272 UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const 273 { 274 return ArcInfo.DataStartPosition + 275 PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; 276 } 277 GetFolderFullPackSizeCDbEx278 UInt64 GetFolderFullPackSize(CNum folderIndex) const 279 { 280 return 281 PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - 282 PackPositions[FoStartPackStreamIndex[folderIndex]]; 283 } 284 GetFolderPackStreamSizeCDbEx285 UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const 286 { 287 size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex; 288 return PackPositions[i + 1] - PackPositions[i]; 289 } 290 GetFilePackSizeCDbEx291 UInt64 GetFilePackSize(CNum fileIndex) const 292 { 293 CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; 294 if (folderIndex != kNumNoIndex) 295 if (FolderStartFileIndex[folderIndex] == fileIndex) 296 return GetFolderFullPackSize(folderIndex); 297 return 0; 298 } 299 }; 300 301 const unsigned kNumBufLevelsMax = 4; 302 303 struct CInByte2 304 { 305 const Byte *_buffer; 306 public: 307 size_t _size; 308 size_t _pos; 309 GetRemCInByte2310 size_t GetRem() const { return _size - _pos; } GetPtrCInByte2311 const Byte *GetPtr() const { return _buffer + _pos; } InitCInByte2312 void Init(const Byte *buffer, size_t size) 313 { 314 _buffer = buffer; 315 _size = size; 316 _pos = 0; 317 } 318 Byte ReadByte(); 319 void ReadBytes(Byte *data, size_t size); SkipDataNoCheckCInByte2320 void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; } 321 void SkipData(UInt64 size); 322 323 void SkipData(); SkipRemCInByte2324 void SkipRem() { _pos = _size; } 325 UInt64 ReadNumber(); 326 CNum ReadNum(); 327 UInt32 ReadUInt32(); 328 UInt64 ReadUInt64(); 329 330 void ParseFolder(CFolder &folder); 331 }; 332 333 class CStreamSwitch; 334 335 const UInt32 kHeaderSize = 32; 336 337 class CInArchive 338 { 339 friend class CStreamSwitch; 340 341 CMyComPtr<IInStream> _stream; 342 343 unsigned _numInByteBufs; 344 CInByte2 _inByteVector[kNumBufLevelsMax]; 345 346 CInByte2 *_inByteBack; 347 bool ThereIsHeaderError; 348 349 UInt64 _arhiveBeginStreamPosition; 350 UInt64 _fileEndPosition; 351 352 Byte _header[kHeaderSize]; 353 354 UInt64 HeadersSize; 355 356 bool _useMixerMT; 357 358 void AddByteStream(const Byte *buffer, size_t size); 359 DeleteByteStream(bool needUpdatePos)360 void DeleteByteStream(bool needUpdatePos) 361 { 362 _numInByteBufs--; 363 if (_numInByteBufs > 0) 364 { 365 _inByteBack = &_inByteVector[_numInByteBufs - 1]; 366 if (needUpdatePos) 367 _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos; 368 } 369 } 370 371 HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); 372 ReadBytes(Byte * data,size_t size)373 void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } ReadByte()374 Byte ReadByte() { return _inByteBack->ReadByte(); } ReadNumber()375 UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } ReadNum()376 CNum ReadNum() { return _inByteBack->ReadNum(); } ReadID()377 UInt64 ReadID() { return _inByteBack->ReadNumber(); } ReadUInt32()378 UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } ReadUInt64()379 UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } SkipData(UInt64 size)380 void SkipData(UInt64 size) { _inByteBack->SkipData(size); } SkipData()381 void SkipData() { _inByteBack->SkipData(); } 382 void WaitId(UInt64 id); 383 384 void Read_UInt32_Vector(CUInt32DefVector &v); 385 386 void ReadArchiveProperties(CInArchiveInfo &archiveInfo); 387 void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs); 388 389 void ReadPackInfo(CFolders &f); 390 391 void ReadUnpackInfo( 392 const CObjectVector<CByteBuffer> *dataVector, 393 CFolders &folders); 394 395 void ReadSubStreamsInfo( 396 CFolders &folders, 397 CRecordVector<UInt64> &unpackSizes, 398 CUInt32DefVector &digests); 399 400 void ReadStreamsInfo( 401 const CObjectVector<CByteBuffer> *dataVector, 402 UInt64 &dataOffset, 403 CFolders &folders, 404 CRecordVector<UInt64> &unpackSizes, 405 CUInt32DefVector &digests); 406 407 void ReadBoolVector(unsigned numItems, CBoolVector &v); 408 void ReadBoolVector2(unsigned numItems, CBoolVector &v); 409 void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, 410 CUInt64DefVector &v, unsigned numItems); 411 HRESULT ReadAndDecodePackedStreams( 412 DECL_EXTERNAL_CODECS_LOC_VARS 413 UInt64 baseOffset, UInt64 &dataOffset, 414 CObjectVector<CByteBuffer> &dataVector 415 _7Z_DECODER_CRYPRO_VARS_DECL 416 ); 417 HRESULT ReadHeader( 418 DECL_EXTERNAL_CODECS_LOC_VARS 419 CDbEx &db 420 _7Z_DECODER_CRYPRO_VARS_DECL 421 ); 422 HRESULT ReadDatabase2( 423 DECL_EXTERNAL_CODECS_LOC_VARS 424 CDbEx &db 425 _7Z_DECODER_CRYPRO_VARS_DECL 426 ); 427 public: CInArchive(bool useMixerMT)428 CInArchive(bool useMixerMT): 429 _numInByteBufs(0), 430 _useMixerMT(useMixerMT) 431 {} 432 433 HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive 434 void Close(); 435 436 HRESULT ReadDatabase( 437 DECL_EXTERNAL_CODECS_LOC_VARS 438 CDbEx &db 439 _7Z_DECODER_CRYPRO_VARS_DECL 440 ); 441 }; 442 443 }} 444 445 #endif 446