1*f6dc9357SAndroid Build Coastguard Worker // Archive/ChmIn.h 2*f6dc9357SAndroid Build Coastguard Worker 3*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_ARCHIVE_CHM_IN_H 4*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_ARCHIVE_CHM_IN_H 5*f6dc9357SAndroid Build Coastguard Worker 6*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyBuffer.h" 7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/MyString.h" 8*f6dc9357SAndroid Build Coastguard Worker 9*f6dc9357SAndroid Build Coastguard Worker #include "../../IStream.h" 10*f6dc9357SAndroid Build Coastguard Worker 11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/InBuffer.h" 12*f6dc9357SAndroid Build Coastguard Worker 13*f6dc9357SAndroid Build Coastguard Worker namespace NArchive { 14*f6dc9357SAndroid Build Coastguard Worker namespace NChm { 15*f6dc9357SAndroid Build Coastguard Worker 16*f6dc9357SAndroid Build Coastguard Worker struct CItem 17*f6dc9357SAndroid Build Coastguard Worker { 18*f6dc9357SAndroid Build Coastguard Worker UInt64 Section; 19*f6dc9357SAndroid Build Coastguard Worker UInt64 Offset; 20*f6dc9357SAndroid Build Coastguard Worker UInt64 Size; 21*f6dc9357SAndroid Build Coastguard Worker AString Name; 22*f6dc9357SAndroid Build Coastguard Worker IsFormatRelatedItemCItem23*f6dc9357SAndroid Build Coastguard Worker bool IsFormatRelatedItem() const 24*f6dc9357SAndroid Build Coastguard Worker { 25*f6dc9357SAndroid Build Coastguard Worker if (Name.Len() < 2) 26*f6dc9357SAndroid Build Coastguard Worker return false; 27*f6dc9357SAndroid Build Coastguard Worker return Name[0] == ':' && Name[1] == ':'; 28*f6dc9357SAndroid Build Coastguard Worker } 29*f6dc9357SAndroid Build Coastguard Worker IsUserItemCItem30*f6dc9357SAndroid Build Coastguard Worker bool IsUserItem() const 31*f6dc9357SAndroid Build Coastguard Worker { 32*f6dc9357SAndroid Build Coastguard Worker if (Name.Len() < 2) 33*f6dc9357SAndroid Build Coastguard Worker return false; 34*f6dc9357SAndroid Build Coastguard Worker return Name[0] == '/'; 35*f6dc9357SAndroid Build Coastguard Worker } 36*f6dc9357SAndroid Build Coastguard Worker IsDirCItem37*f6dc9357SAndroid Build Coastguard Worker bool IsDir() const 38*f6dc9357SAndroid Build Coastguard Worker { 39*f6dc9357SAndroid Build Coastguard Worker if (Name.IsEmpty()) 40*f6dc9357SAndroid Build Coastguard Worker return false; 41*f6dc9357SAndroid Build Coastguard Worker return (Name.Back() == '/'); 42*f6dc9357SAndroid Build Coastguard Worker } 43*f6dc9357SAndroid Build Coastguard Worker }; 44*f6dc9357SAndroid Build Coastguard Worker 45*f6dc9357SAndroid Build Coastguard Worker 46*f6dc9357SAndroid Build Coastguard Worker struct CDatabase 47*f6dc9357SAndroid Build Coastguard Worker { 48*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CItem> Items; 49*f6dc9357SAndroid Build Coastguard Worker UInt64 StartPosition; 50*f6dc9357SAndroid Build Coastguard Worker UInt64 ContentOffset; 51*f6dc9357SAndroid Build Coastguard Worker AString NewFormatString; 52*f6dc9357SAndroid Build Coastguard Worker bool Help2Format; 53*f6dc9357SAndroid Build Coastguard Worker bool NewFormat; 54*f6dc9357SAndroid Build Coastguard Worker UInt64 PhySize; 55*f6dc9357SAndroid Build Coastguard Worker UpdatePhySizeCDatabase56*f6dc9357SAndroid Build Coastguard Worker void UpdatePhySize(UInt64 v) { if (PhySize < v) PhySize = v; } 57*f6dc9357SAndroid Build Coastguard Worker FindItemCDatabase58*f6dc9357SAndroid Build Coastguard Worker int FindItem(const AString &name) const 59*f6dc9357SAndroid Build Coastguard Worker { 60*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, Items) 61*f6dc9357SAndroid Build Coastguard Worker if (Items[i].Name == name) 62*f6dc9357SAndroid Build Coastguard Worker return (int)i; 63*f6dc9357SAndroid Build Coastguard Worker return -1; 64*f6dc9357SAndroid Build Coastguard Worker } 65*f6dc9357SAndroid Build Coastguard Worker ClearCDatabase66*f6dc9357SAndroid Build Coastguard Worker void Clear() 67*f6dc9357SAndroid Build Coastguard Worker { 68*f6dc9357SAndroid Build Coastguard Worker NewFormat = false; 69*f6dc9357SAndroid Build Coastguard Worker NewFormatString.Empty(); 70*f6dc9357SAndroid Build Coastguard Worker Help2Format = false; 71*f6dc9357SAndroid Build Coastguard Worker Items.Clear(); 72*f6dc9357SAndroid Build Coastguard Worker StartPosition = 0; 73*f6dc9357SAndroid Build Coastguard Worker PhySize = 0; 74*f6dc9357SAndroid Build Coastguard Worker } 75*f6dc9357SAndroid Build Coastguard Worker }; 76*f6dc9357SAndroid Build Coastguard Worker 77*f6dc9357SAndroid Build Coastguard Worker 78*f6dc9357SAndroid Build Coastguard Worker const UInt32 kBlockSize = 1 << 15; 79*f6dc9357SAndroid Build Coastguard Worker 80*f6dc9357SAndroid Build Coastguard Worker struct CResetTable 81*f6dc9357SAndroid Build Coastguard Worker { 82*f6dc9357SAndroid Build Coastguard Worker UInt64 UncompressedSize; 83*f6dc9357SAndroid Build Coastguard Worker UInt64 CompressedSize; 84*f6dc9357SAndroid Build Coastguard Worker // unsigned BlockSizeBits; 85*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt64> ResetOffsets; 86*f6dc9357SAndroid Build Coastguard Worker CResetTableCResetTable87*f6dc9357SAndroid Build Coastguard Worker CResetTable(): 88*f6dc9357SAndroid Build Coastguard Worker UncompressedSize(0), 89*f6dc9357SAndroid Build Coastguard Worker CompressedSize(0) 90*f6dc9357SAndroid Build Coastguard Worker {} 91*f6dc9357SAndroid Build Coastguard Worker GetCompressedSizeOfBlocksCResetTable92*f6dc9357SAndroid Build Coastguard Worker bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const 93*f6dc9357SAndroid Build Coastguard Worker { 94*f6dc9357SAndroid Build Coastguard Worker if (blockIndex >= ResetOffsets.Size()) 95*f6dc9357SAndroid Build Coastguard Worker return false; 96*f6dc9357SAndroid Build Coastguard Worker UInt64 startPos = ResetOffsets[(unsigned)blockIndex]; 97*f6dc9357SAndroid Build Coastguard Worker if (blockIndex + numBlocks >= ResetOffsets.Size()) 98*f6dc9357SAndroid Build Coastguard Worker size = CompressedSize - startPos; 99*f6dc9357SAndroid Build Coastguard Worker else 100*f6dc9357SAndroid Build Coastguard Worker size = ResetOffsets[(unsigned)(blockIndex + numBlocks)] - startPos; 101*f6dc9357SAndroid Build Coastguard Worker return true; 102*f6dc9357SAndroid Build Coastguard Worker } 103*f6dc9357SAndroid Build Coastguard Worker GetCompressedSizeOfBlockCResetTable104*f6dc9357SAndroid Build Coastguard Worker bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const 105*f6dc9357SAndroid Build Coastguard Worker { 106*f6dc9357SAndroid Build Coastguard Worker return GetCompressedSizeOfBlocks(blockIndex, 1, size); 107*f6dc9357SAndroid Build Coastguard Worker } 108*f6dc9357SAndroid Build Coastguard Worker GetNumBlocksCResetTable109*f6dc9357SAndroid Build Coastguard Worker UInt64 GetNumBlocks(UInt64 size) const 110*f6dc9357SAndroid Build Coastguard Worker { 111*f6dc9357SAndroid Build Coastguard Worker return (size + kBlockSize - 1) / kBlockSize; 112*f6dc9357SAndroid Build Coastguard Worker } 113*f6dc9357SAndroid Build Coastguard Worker }; 114*f6dc9357SAndroid Build Coastguard Worker 115*f6dc9357SAndroid Build Coastguard Worker 116*f6dc9357SAndroid Build Coastguard Worker struct CLzxInfo 117*f6dc9357SAndroid Build Coastguard Worker { 118*f6dc9357SAndroid Build Coastguard Worker UInt32 Version; 119*f6dc9357SAndroid Build Coastguard Worker 120*f6dc9357SAndroid Build Coastguard Worker unsigned ResetIntervalBits; 121*f6dc9357SAndroid Build Coastguard Worker unsigned WindowSizeBits; 122*f6dc9357SAndroid Build Coastguard Worker UInt32 CacheSize; 123*f6dc9357SAndroid Build Coastguard Worker 124*f6dc9357SAndroid Build Coastguard Worker CResetTable ResetTable; 125*f6dc9357SAndroid Build Coastguard Worker CLzxInfoCLzxInfo126*f6dc9357SAndroid Build Coastguard Worker CLzxInfo(): 127*f6dc9357SAndroid Build Coastguard Worker Version(0), 128*f6dc9357SAndroid Build Coastguard Worker ResetIntervalBits(0), 129*f6dc9357SAndroid Build Coastguard Worker WindowSizeBits(0), 130*f6dc9357SAndroid Build Coastguard Worker CacheSize(0) 131*f6dc9357SAndroid Build Coastguard Worker {} 132*f6dc9357SAndroid Build Coastguard Worker GetNumDictBitsCLzxInfo133*f6dc9357SAndroid Build Coastguard Worker unsigned GetNumDictBits() const 134*f6dc9357SAndroid Build Coastguard Worker { 135*f6dc9357SAndroid Build Coastguard Worker if (Version == 2 || Version == 3) 136*f6dc9357SAndroid Build Coastguard Worker return 15 + WindowSizeBits; 137*f6dc9357SAndroid Build Coastguard Worker return 0; 138*f6dc9357SAndroid Build Coastguard Worker } 139*f6dc9357SAndroid Build Coastguard Worker GetFolderSizeCLzxInfo140*f6dc9357SAndroid Build Coastguard Worker UInt64 GetFolderSize() const { return (UInt64)kBlockSize << ResetIntervalBits; } GetFolderCLzxInfo141*f6dc9357SAndroid Build Coastguard Worker UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); } GetFolderPosCLzxInfo142*f6dc9357SAndroid Build Coastguard Worker UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); } GetBlockIndexFromFolderIndexCLzxInfo143*f6dc9357SAndroid Build Coastguard Worker UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex << ResetIntervalBits; } 144*f6dc9357SAndroid Build Coastguard Worker GetOffsetOfFolderCLzxInfo145*f6dc9357SAndroid Build Coastguard Worker bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const 146*f6dc9357SAndroid Build Coastguard Worker { 147*f6dc9357SAndroid Build Coastguard Worker const UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex); 148*f6dc9357SAndroid Build Coastguard Worker if (blockIndex >= ResetTable.ResetOffsets.Size()) 149*f6dc9357SAndroid Build Coastguard Worker return false; 150*f6dc9357SAndroid Build Coastguard Worker offset = ResetTable.ResetOffsets[(unsigned)blockIndex]; 151*f6dc9357SAndroid Build Coastguard Worker return true; 152*f6dc9357SAndroid Build Coastguard Worker } 153*f6dc9357SAndroid Build Coastguard Worker GetCompressedSizeOfFolderCLzxInfo154*f6dc9357SAndroid Build Coastguard Worker bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const 155*f6dc9357SAndroid Build Coastguard Worker { 156*f6dc9357SAndroid Build Coastguard Worker UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex); 157*f6dc9357SAndroid Build Coastguard Worker return ResetTable.GetCompressedSizeOfBlocks(blockIndex, (UInt32)1 << ResetIntervalBits, size); 158*f6dc9357SAndroid Build Coastguard Worker } 159*f6dc9357SAndroid Build Coastguard Worker }; 160*f6dc9357SAndroid Build Coastguard Worker 161*f6dc9357SAndroid Build Coastguard Worker 162*f6dc9357SAndroid Build Coastguard Worker struct CMethodInfo 163*f6dc9357SAndroid Build Coastguard Worker { 164*f6dc9357SAndroid Build Coastguard Worker Byte Guid[16]; 165*f6dc9357SAndroid Build Coastguard Worker // CByteBuffer ControlData; 166*f6dc9357SAndroid Build Coastguard Worker CLzxInfo LzxInfo; 167*f6dc9357SAndroid Build Coastguard Worker 168*f6dc9357SAndroid Build Coastguard Worker bool IsLzx() const; 169*f6dc9357SAndroid Build Coastguard Worker bool IsDes() const; 170*f6dc9357SAndroid Build Coastguard Worker AString GetGuidString() const; 171*f6dc9357SAndroid Build Coastguard Worker AString GetName() const; 172*f6dc9357SAndroid Build Coastguard Worker }; 173*f6dc9357SAndroid Build Coastguard Worker 174*f6dc9357SAndroid Build Coastguard Worker 175*f6dc9357SAndroid Build Coastguard Worker struct CSectionInfo 176*f6dc9357SAndroid Build Coastguard Worker { 177*f6dc9357SAndroid Build Coastguard Worker UInt64 Offset; 178*f6dc9357SAndroid Build Coastguard Worker UInt64 CompressedSize; 179*f6dc9357SAndroid Build Coastguard Worker UInt64 UncompressedSize; 180*f6dc9357SAndroid Build Coastguard Worker 181*f6dc9357SAndroid Build Coastguard Worker AString Name; 182*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CMethodInfo> Methods; 183*f6dc9357SAndroid Build Coastguard Worker 184*f6dc9357SAndroid Build Coastguard Worker bool IsLzx() const; 185*f6dc9357SAndroid Build Coastguard Worker UString GetMethodName() const; 186*f6dc9357SAndroid Build Coastguard Worker }; 187*f6dc9357SAndroid Build Coastguard Worker 188*f6dc9357SAndroid Build Coastguard Worker class CFilesDatabase: public CDatabase 189*f6dc9357SAndroid Build Coastguard Worker { 190*f6dc9357SAndroid Build Coastguard Worker public: 191*f6dc9357SAndroid Build Coastguard Worker CUIntVector Indices; 192*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CSectionInfo> Sections; 193*f6dc9357SAndroid Build Coastguard Worker bool LowLevel; 194*f6dc9357SAndroid Build Coastguard Worker GetFileSize(unsigned fileIndex)195*f6dc9357SAndroid Build Coastguard Worker UInt64 GetFileSize(unsigned fileIndex) const { return Items[Indices[fileIndex]].Size; } GetFileOffset(unsigned fileIndex)196*f6dc9357SAndroid Build Coastguard Worker UInt64 GetFileOffset(unsigned fileIndex) const { return Items[Indices[fileIndex]].Offset; } 197*f6dc9357SAndroid Build Coastguard Worker GetFolder(unsigned fileIndex)198*f6dc9357SAndroid Build Coastguard Worker UInt64 GetFolder(unsigned fileIndex) const 199*f6dc9357SAndroid Build Coastguard Worker { 200*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[Indices[fileIndex]]; 201*f6dc9357SAndroid Build Coastguard Worker if (item.Section < Sections.Size()) 202*f6dc9357SAndroid Build Coastguard Worker { 203*f6dc9357SAndroid Build Coastguard Worker const CSectionInfo §ion = Sections[(unsigned)item.Section]; 204*f6dc9357SAndroid Build Coastguard Worker if (section.IsLzx()) 205*f6dc9357SAndroid Build Coastguard Worker return section.Methods[0].LzxInfo.GetFolder(item.Offset); 206*f6dc9357SAndroid Build Coastguard Worker } 207*f6dc9357SAndroid Build Coastguard Worker return 0; 208*f6dc9357SAndroid Build Coastguard Worker } 209*f6dc9357SAndroid Build Coastguard Worker GetLastFolder(unsigned fileIndex)210*f6dc9357SAndroid Build Coastguard Worker UInt64 GetLastFolder(unsigned fileIndex) const 211*f6dc9357SAndroid Build Coastguard Worker { 212*f6dc9357SAndroid Build Coastguard Worker const CItem &item = Items[Indices[fileIndex]]; 213*f6dc9357SAndroid Build Coastguard Worker if (item.Section < Sections.Size()) 214*f6dc9357SAndroid Build Coastguard Worker { 215*f6dc9357SAndroid Build Coastguard Worker const CSectionInfo §ion = Sections[(unsigned)item.Section]; 216*f6dc9357SAndroid Build Coastguard Worker if (section.IsLzx()) 217*f6dc9357SAndroid Build Coastguard Worker return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1); 218*f6dc9357SAndroid Build Coastguard Worker } 219*f6dc9357SAndroid Build Coastguard Worker return 0; 220*f6dc9357SAndroid Build Coastguard Worker } 221*f6dc9357SAndroid Build Coastguard Worker HighLevelClear()222*f6dc9357SAndroid Build Coastguard Worker void HighLevelClear() 223*f6dc9357SAndroid Build Coastguard Worker { 224*f6dc9357SAndroid Build Coastguard Worker LowLevel = true; 225*f6dc9357SAndroid Build Coastguard Worker Indices.Clear(); 226*f6dc9357SAndroid Build Coastguard Worker Sections.Clear(); 227*f6dc9357SAndroid Build Coastguard Worker } 228*f6dc9357SAndroid Build Coastguard Worker Clear()229*f6dc9357SAndroid Build Coastguard Worker void Clear() 230*f6dc9357SAndroid Build Coastguard Worker { 231*f6dc9357SAndroid Build Coastguard Worker CDatabase::Clear(); 232*f6dc9357SAndroid Build Coastguard Worker HighLevelClear(); 233*f6dc9357SAndroid Build Coastguard Worker } 234*f6dc9357SAndroid Build Coastguard Worker 235*f6dc9357SAndroid Build Coastguard Worker void SetIndices(); 236*f6dc9357SAndroid Build Coastguard Worker void Sort(); 237*f6dc9357SAndroid Build Coastguard Worker bool Check(); 238*f6dc9357SAndroid Build Coastguard Worker bool CheckSectionRefs(); 239*f6dc9357SAndroid Build Coastguard Worker }; 240*f6dc9357SAndroid Build Coastguard Worker 241*f6dc9357SAndroid Build Coastguard Worker 242*f6dc9357SAndroid Build Coastguard Worker class CInArchive 243*f6dc9357SAndroid Build Coastguard Worker { 244*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> m_InStreamRef; 245*f6dc9357SAndroid Build Coastguard Worker ::CInBuffer _inBuffer; 246*f6dc9357SAndroid Build Coastguard Worker UInt64 _chunkSize; 247*f6dc9357SAndroid Build Coastguard Worker bool _help2; 248*f6dc9357SAndroid Build Coastguard Worker 249*f6dc9357SAndroid Build Coastguard Worker Byte ReadByte(); 250*f6dc9357SAndroid Build Coastguard Worker void ReadBytes(Byte *data, UInt32 size); 251*f6dc9357SAndroid Build Coastguard Worker void Skip(size_t size); 252*f6dc9357SAndroid Build Coastguard Worker UInt16 ReadUInt16(); 253*f6dc9357SAndroid Build Coastguard Worker UInt32 ReadUInt32(); 254*f6dc9357SAndroid Build Coastguard Worker UInt64 ReadUInt64(); 255*f6dc9357SAndroid Build Coastguard Worker UInt64 ReadEncInt(); 256*f6dc9357SAndroid Build Coastguard Worker void ReadString(unsigned size, AString &s); 257*f6dc9357SAndroid Build Coastguard Worker void ReadUString(unsigned size, UString &s); 258*f6dc9357SAndroid Build Coastguard Worker void ReadGUID(Byte *g); 259*f6dc9357SAndroid Build Coastguard Worker 260*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size); 261*f6dc9357SAndroid Build Coastguard Worker 262*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadDirEntry(CDatabase &database); 263*f6dc9357SAndroid Build Coastguard Worker HRESULT DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name); 264*f6dc9357SAndroid Build Coastguard Worker 265*f6dc9357SAndroid Build Coastguard Worker public: 266*f6dc9357SAndroid Build Coastguard Worker bool IsArc; 267*f6dc9357SAndroid Build Coastguard Worker bool HeadersError; 268*f6dc9357SAndroid Build Coastguard Worker bool UnexpectedEnd; 269*f6dc9357SAndroid Build Coastguard Worker bool UnsupportedFeature; 270*f6dc9357SAndroid Build Coastguard Worker CInArchive(bool help2)271*f6dc9357SAndroid Build Coastguard Worker CInArchive(bool help2) { _help2 = help2; } 272*f6dc9357SAndroid Build Coastguard Worker 273*f6dc9357SAndroid Build Coastguard Worker HRESULT OpenChm(IInStream *inStream, CDatabase &database); 274*f6dc9357SAndroid Build Coastguard Worker HRESULT OpenHelp2(IInStream *inStream, CDatabase &database); 275*f6dc9357SAndroid Build Coastguard Worker HRESULT OpenHighLevel(IInStream *inStream, CFilesDatabase &database); 276*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database); 277*f6dc9357SAndroid Build Coastguard Worker HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database); 278*f6dc9357SAndroid Build Coastguard Worker }; 279*f6dc9357SAndroid Build Coastguard Worker 280*f6dc9357SAndroid Build Coastguard Worker }} 281*f6dc9357SAndroid Build Coastguard Worker 282*f6dc9357SAndroid Build Coastguard Worker #endif 283