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(size_t folderIndex, size_t indexInFolder) const 277 { 278 return ArcInfo.DataStartPosition + PackPositions.ConstData() 279 [FoStartPackStreamIndex.ConstData()[folderIndex] + indexInFolder]; 280 } 281 GetFolderFullPackSizeCDbEx282 UInt64 GetFolderFullPackSize(size_t folderIndex) const 283 { 284 return 285 PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex + 1]] - 286 PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex]]; 287 } 288 GetFolderPackStreamSizeCDbEx289 UInt64 GetFolderPackStreamSize(size_t folderIndex, size_t streamIndex) const 290 { 291 const size_t i = FoStartPackStreamIndex.ConstData()[folderIndex] + streamIndex; 292 return PackPositions.ConstData()[i + 1] - 293 PackPositions.ConstData()[i]; 294 } 295 296 /* 297 UInt64 GetFilePackSize(size_t fileIndex) const 298 { 299 const CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; 300 if (folderIndex != kNumNoIndex) 301 if (FolderStartFileIndex[folderIndex] == fileIndex) 302 return GetFolderFullPackSize(folderIndex); 303 return 0; 304 } 305 */ 306 }; 307 308 const unsigned kNumBufLevelsMax = 4; 309 310 struct CInByte2 311 { 312 const Byte *_buffer; 313 public: 314 size_t _size; 315 size_t _pos; 316 GetRemCInByte2317 size_t GetRem() const { return _size - _pos; } GetPtrCInByte2318 const Byte *GetPtr() const { return _buffer + _pos; } InitCInByte2319 void Init(const Byte *buffer, size_t size) 320 { 321 _buffer = buffer; 322 _size = size; 323 _pos = 0; 324 } 325 Byte ReadByte(); 326 void ReadBytes(Byte *data, size_t size); SkipDataNoCheckCInByte2327 void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; } 328 void SkipData(UInt64 size); 329 330 void SkipData(); SkipRemCInByte2331 void SkipRem() { _pos = _size; } 332 UInt64 ReadNumber(); 333 CNum ReadNum(); 334 UInt32 ReadUInt32(); 335 UInt64 ReadUInt64(); 336 337 void ParseFolder(CFolder &folder); 338 }; 339 340 class CStreamSwitch; 341 342 const UInt32 kHeaderSize = 32; 343 344 class CInArchive 345 { 346 friend class CStreamSwitch; 347 348 CMyComPtr<IInStream> _stream; 349 350 unsigned _numInByteBufs; 351 CInByte2 _inByteVector[kNumBufLevelsMax]; 352 353 CInByte2 *_inByteBack; 354 bool ThereIsHeaderError; 355 356 UInt64 _arhiveBeginStreamPosition; 357 UInt64 _fileEndPosition; 358 359 UInt64 _rangeLimit; // relative to position after StartHeader (32 bytes) 360 361 Byte _header[kHeaderSize]; 362 363 UInt64 HeadersSize; 364 365 bool _useMixerMT; 366 367 void AddByteStream(const Byte *buffer, size_t size); 368 DeleteByteStream(bool needUpdatePos)369 void DeleteByteStream(bool needUpdatePos) 370 { 371 _numInByteBufs--; 372 if (_numInByteBufs > 0) 373 { 374 _inByteBack = &_inByteVector[_numInByteBufs - 1]; 375 if (needUpdatePos) 376 _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos; 377 } 378 } 379 380 HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); 381 ReadBytes(Byte * data,size_t size)382 void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); } ReadByte()383 Byte ReadByte() { return _inByteBack->ReadByte(); } ReadNumber()384 UInt64 ReadNumber() { return _inByteBack->ReadNumber(); } ReadNum()385 CNum ReadNum() { return _inByteBack->ReadNum(); } ReadID()386 UInt64 ReadID() { return _inByteBack->ReadNumber(); } ReadUInt32()387 UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); } ReadUInt64()388 UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); } SkipData(UInt64 size)389 void SkipData(UInt64 size) { _inByteBack->SkipData(size); } SkipData()390 void SkipData() { _inByteBack->SkipData(); } 391 void WaitId(UInt64 id); 392 393 void Read_UInt32_Vector(CUInt32DefVector &v); 394 395 void ReadArchiveProperties(CInArchiveInfo &archiveInfo); 396 void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs); 397 398 void ReadPackInfo(CFolders &f); 399 400 void ReadUnpackInfo( 401 const CObjectVector<CByteBuffer> *dataVector, 402 CFolders &folders); 403 404 void ReadSubStreamsInfo( 405 CFolders &folders, 406 CRecordVector<UInt64> &unpackSizes, 407 CUInt32DefVector &digests); 408 409 void ReadStreamsInfo( 410 const CObjectVector<CByteBuffer> *dataVector, 411 UInt64 &dataOffset, 412 CFolders &folders, 413 CRecordVector<UInt64> &unpackSizes, 414 CUInt32DefVector &digests); 415 416 void ReadBoolVector(unsigned numItems, CBoolVector &v); 417 void ReadBoolVector2(unsigned numItems, CBoolVector &v); 418 void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector, 419 CUInt64DefVector &v, unsigned numItems); 420 HRESULT ReadAndDecodePackedStreams( 421 DECL_EXTERNAL_CODECS_LOC_VARS 422 UInt64 baseOffset, UInt64 &dataOffset, 423 CObjectVector<CByteBuffer> &dataVector 424 Z7_7Z_DECODER_CRYPRO_VARS_DECL 425 ); 426 HRESULT ReadHeader( 427 DECL_EXTERNAL_CODECS_LOC_VARS 428 CDbEx &db 429 Z7_7Z_DECODER_CRYPRO_VARS_DECL 430 ); 431 HRESULT ReadDatabase2( 432 DECL_EXTERNAL_CODECS_LOC_VARS 433 CDbEx &db 434 Z7_7Z_DECODER_CRYPRO_VARS_DECL 435 ); 436 public: CInArchive(bool useMixerMT)437 CInArchive(bool useMixerMT): 438 _numInByteBufs(0), 439 _useMixerMT(useMixerMT) 440 {} 441 442 HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive 443 void Close(); 444 445 HRESULT ReadDatabase( 446 DECL_EXTERNAL_CODECS_LOC_VARS 447 CDbEx &db 448 Z7_7Z_DECODER_CRYPRO_VARS_DECL 449 ); 450 }; 451 452 }} 453 454 #endif 455