package org.j7zip.SevenZip.Archive.SevenZip; import java.io.IOException; import org.j7zip.Common.BoolVector; import org.j7zip.Common.ByteBuffer; import org.j7zip.Common.CRC; import org.j7zip.Common.IntVector; import org.j7zip.Common.LongVector; import org.j7zip.Common.ObjectVector; import org.j7zip.SevenZip.HRESULT; import org.j7zip.SevenZip.IInStream; import org.j7zip.SevenZip.Archive.Common.BindPair; import org.j7zip.SevenZip.Common.StreamUtils; class InArchive extends Header { // CNum static public final int kNumMax = 0x7FFFFFFF; static public final int kNumNoIndex = 0xFFFFFFFF; IInStream _stream; // CMyComPtr<IInStream> _stream; ObjectVector<InByte2> _inByteVector; InByte2 _inByteBack; long _arhiveBeginStreamPosition; long _position; public InArchive() { _inByteVector = new ObjectVector<>(); _inByteBack = new InByte2(); } public void AddByteStream(byte [] buffer, int size) { _inByteVector.add(new InByte2()); _inByteBack = _inByteVector.Back(); _inByteBack.Init(buffer, size); } void DeleteByteStream() { _inByteVector.DeleteBack(); if (!_inByteVector.isEmpty()) _inByteBack = _inByteVector.Back(); } static boolean TestSignatureCandidate(byte [] testBytes, int off) { for (int i = 0; i < kSignatureSize; i++) { // System.out.println(" " + i + ":" + testBytes[i] + " " + kSignature[i]); if (testBytes[i + off] != kSignature[i]) return false; } return true; } int ReadDirect(IInStream stream, // IInStream *stream, byte [] data, // void *data, int off, int size // UInt32 size, ) throws IOException { int realProcessedSize = StreamUtils.ReadStream(stream, data, off, size); if (realProcessedSize != -1) _position += realProcessedSize; return realProcessedSize; } int ReadDirect(byte [] data, int size) throws IOException { return ReadDirect(_stream, data, 0, size); } int SafeReadDirectUInt32() throws IOException { int val = 0; byte [] b = new byte[4]; int realProcessedSize = ReadDirect(b, 4); if (realProcessedSize != 4) throw new IOException("Unexpected End Of Archive"); // throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); for (int i = 0; i < 4; i++) { val |= ((b[i] & 0xff) << (8 * i)); } return val; } int ReadUInt32() throws IOException { int value = 0; for (int i = 0; i < 4; i++) { int b = ReadByte(); value |= ((b) << (8 * i)); } return value; } long ReadUInt64() throws IOException { long value = 0; for (int i = 0; i < 8; i++) { int b = ReadByte(); value |= (((long)b) << (8 * i)); } return value; } int ReadBytes(byte data[], int size) throws IOException { if (!_inByteBack.ReadBytes(data, size)) return HRESULT.E_FAIL; return HRESULT.S_OK; } int ReadByte() throws IOException { return _inByteBack.ReadByte(); } long SafeReadDirectUInt64() throws IOException { long val = 0; byte [] b = new byte[8]; int realProcessedSize = ReadDirect(b, 8); if (realProcessedSize != 8) throw new IOException("Unexpected End Of Archive"); // throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); for (int i = 0; i < 8; i++) { val |= ((long)(b[i] & 0xFF) << (8 * i)); } return val; } char ReadWideCharLE() throws IOException { int b1 = _inByteBack.ReadByte(); int b2 = _inByteBack.ReadByte(); char c = (char)(((char)(b2) << 8) + b1); return c; } long ReadNumber() throws IOException { int firstByte = ReadByte(); int mask = 0x80; long value = 0; for (int i = 0; i < 8; i++) { if ((firstByte & mask) == 0) { long highPart = firstByte & (mask - 1); value += (highPart << (i * 8)); return value; } int b = ReadByte(); if (b < 0) throw new IOException("ReadNumber - Can't read stream"); value |= (((long)b) << (8 * i)); mask >>= 1; } return value; } int ReadNum() throws IOException { // CNum long value64 = ReadNumber(); if (value64 > InArchive.kNumMax) throw new IOException("ReadNum - value > CNum.kNumMax"); // return E_FAIL; return (int)value64; } long ReadID() throws IOException { return ReadNumber(); } int FindAndReadSignature( IInStream stream, // IInStream *stream, long searchHeaderSizeLimit // const UInt64 *searchHeaderSizeLimit ) throws IOException { _position = _arhiveBeginStreamPosition; stream.Seek(_arhiveBeginStreamPosition,IInStream.STREAM_SEEK_SET); byte [] signature = new byte[kSignatureSize]; int processedSize = ReadDirect(stream, signature, 0, kSignatureSize); if(processedSize != kSignatureSize) return HRESULT.S_FALSE; if (TestSignatureCandidate(signature,0)) return HRESULT.S_OK; // SFX support ByteBuffer byteBuffer = new ByteBuffer(); final int kBufferSize = (1 << 16); byteBuffer.SetCapacity(kBufferSize); byte [] buffer = byteBuffer.data(); int numPrevBytes = kSignatureSize - 1; System.arraycopy(signature,1,buffer,0,numPrevBytes); long curTestPos = _arhiveBeginStreamPosition + 1; for (;;) { if (searchHeaderSizeLimit != -1) if (curTestPos - _arhiveBeginStreamPosition > searchHeaderSizeLimit) break; int numReadBytes = kBufferSize - numPrevBytes; // RINOK(ReadDirect(stream, buffer + numPrevBytes, numReadBytes, &processedSize)); processedSize = ReadDirect(stream, buffer,numPrevBytes, numReadBytes); if (processedSize == -1) return HRESULT.S_FALSE; int numBytesInBuffer = numPrevBytes + processedSize; if (numBytesInBuffer < kSignatureSize) break; int numTests = numBytesInBuffer - kSignatureSize + 1; for(int pos = 0; pos < numTests; pos++, curTestPos++) { if (TestSignatureCandidate(buffer , pos)) { _arhiveBeginStreamPosition = curTestPos; _position = curTestPos + kSignatureSize; stream.Seek(_position, IInStream.STREAM_SEEK_SET); return HRESULT.S_OK; } } numPrevBytes = numBytesInBuffer - numTests; System.arraycopy(buffer,numTests,buffer,0,numPrevBytes); } return HRESULT.S_FALSE; } int SkeepData(long size) throws IOException { for (long i = 0; i < size; i++) { /*int temp =*/ ReadByte(); } return HRESULT.S_OK; } int SkeepData() throws IOException { long size = ReadNumber(); return SkeepData(size); } int ReadArchiveProperties(InArchiveInfo archiveInfo) throws IOException { for (;;) { long type = ReadID(); if (type == NID.kEnd) break; SkeepData(); } return HRESULT.S_OK; } int GetNextFolderItem(Folder folder) throws IOException { int numCoders = ReadNum(); folder.Coders.clear(); folder.Coders.Reserve(numCoders); int numInStreams = 0; int numOutStreams = 0; int i; for (i = 0; i < numCoders; i++) { folder.Coders.add(new CoderInfo()); CoderInfo coder = folder.Coders.Back(); for (;;) { coder.AltCoders.add(new AltCoderInfo()); AltCoderInfo altCoder = coder.AltCoders.Back(); int mainByte = ReadByte(); altCoder.MethodID.IDSize = (byte)(mainByte & 0xF); int ret = ReadBytes(altCoder.MethodID.ID, altCoder.MethodID.IDSize); if (ret != HRESULT.S_OK) return ret; if ((mainByte & 0x10) != 0) { coder.NumInStreams = ReadNum(); coder.NumOutStreams = ReadNum(); } else { coder.NumInStreams = 1; coder.NumOutStreams = 1; } if ((mainByte & 0x20) != 0) { int propertiesSize = ReadNum(); altCoder.Properties.SetCapacity(propertiesSize); // RINOK(ReadBytes((Byte *)altCoder.Properties, (size_t)propertiesSize)); ret = ReadBytes(altCoder.Properties.data(), propertiesSize); } if ((mainByte & 0x80) == 0) break; } numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } // RINOK(ReadNumber(numBindPairs)); int numBindPairs = numOutStreams - 1; folder.BindPairs.clear(); folder.BindPairs.Reserve(numBindPairs); for (i = 0; i < numBindPairs; i++) { BindPair bindPair = new BindPair(); bindPair.InIndex = ReadNum(); bindPair.OutIndex = ReadNum(); folder.BindPairs.add(bindPair); } int numPackedStreams = numInStreams - numBindPairs; folder.PackStreams.Reserve(numPackedStreams); if (numPackedStreams == 1) { for (int j = 0; j < numInStreams; j++) if (folder.FindBindPairForInStream(j) < 0) { folder.PackStreams.add(j); break; } } else for(i = 0; i < numPackedStreams; i++) { int packStreamInfo = ReadNum(); folder.PackStreams.add(packStreamInfo); } return HRESULT.S_OK; } int WaitAttribute(long attribute) throws IOException { for (;;) { long type = ReadID(); if (type == attribute) return HRESULT.S_OK; if (type == NID.kEnd) return HRESULT.S_FALSE; int ret = SkeepData(); if (ret != HRESULT.S_OK) return ret; } } int Open( IInStream stream, // IInStream *stream long searchHeaderSizeLimit // const UInt64 *searchHeaderSizeLimit ) throws IOException { Close(); _arhiveBeginStreamPosition = stream.Seek(0, IInStream.STREAM_SEEK_CUR); _position = _arhiveBeginStreamPosition; int ret = FindAndReadSignature(stream, searchHeaderSizeLimit); if (ret != HRESULT.S_OK) return ret; _stream = stream; return HRESULT.S_OK; } void Close() throws IOException { if (_stream != null) _stream.close(); // _stream.Release(); _stream = null; } int ReadStreamsInfo( ObjectVector<ByteBuffer> dataVector, long [] dataOffset, LongVector packSizes, BoolVector packCRCsDefined, IntVector packCRCs, ObjectVector<Folder> folders, IntVector numUnPackStreamsInFolders, LongVector unPackSizes, BoolVector digestsDefined, IntVector digests) throws IOException { for (;;) { long type = ReadID(); switch((int)type) { case NID.kEnd: return HRESULT.S_OK; case NID.kPackInfo: { int result = ReadPackInfo(dataOffset, packSizes, packCRCsDefined, packCRCs); if (result != HRESULT.S_OK) return result; break; } case NID.kUnPackInfo: { int result = ReadUnPackInfo(dataVector, folders); if (result != HRESULT.S_OK) return result; break; } case NID.kSubStreamsInfo: { int result = ReadSubStreamsInfo(folders, numUnPackStreamsInFolders, unPackSizes, digestsDefined, digests); if (result != HRESULT.S_OK) return result; break; } } } } int ReadFileNames(ObjectVector<FileItem> files) throws IOException { for(int i = 0; i < files.size(); i++) { String name = new String(); for (;;) { char c = ReadWideCharLE(); if (c == '\0') break; name += c; } files.get(i).name = name; } return HRESULT.S_OK; } int ReadBoolVector(int numItems, BoolVector v) throws IOException { v.clear(); v.Reserve(numItems); int b = 0; int mask = 0; for(int i = 0; i < numItems; i++) { if (mask == 0) { b = ReadByte(); mask = 0x80; } v.add((b & mask) != 0); mask >>= 1; } return HRESULT.S_OK; } int ReadBoolVector2(int numItems, BoolVector v) throws IOException { // CBoolVector int allAreDefined = ReadByte(); if (allAreDefined == 0) return ReadBoolVector(numItems, v); v.clear(); v.Reserve(numItems); for (int i = 0; i < numItems; i++) v.add(true); return HRESULT.S_OK; } int ReadHashDigests(int numItems, BoolVector digestsDefined, IntVector digests) throws IOException { int ret = ReadBoolVector2(numItems, digestsDefined); if (ret != HRESULT.S_OK) return ret; digests.clear(); digests.Reserve(numItems); for(int i = 0; i < numItems; i++) { int crc = 0; if (digestsDefined.get(i)) crc = ReadUInt32(); digests.add(crc); } return HRESULT.S_OK; } int ReadPackInfo( long [] dataOffset, // UInt64 &dataOffset, LongVector packSizes, // CRecordVector<UInt64> &packSizes, BoolVector packCRCsDefined, // CRecordVector<bool> &packCRCsDefined, IntVector packCRCs) // CRecordVector<UInt32> &packCRCs) throws IOException { dataOffset[0] = ReadNumber(); int numPackStreams = ReadNum(); int ret = WaitAttribute(NID.kSize); if (ret != HRESULT.S_OK) return ret; packSizes.clear(); packSizes.Reserve(numPackStreams); for(int i = 0; i < numPackStreams; i++) // CNum i { long size = ReadNumber(); packSizes.add(size); } long type; for (;;) { type = ReadID(); if (type == NID.kEnd) break; if (type == NID.kCRC) { ret = ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs); if (ret != HRESULT.S_OK) return ret; continue; } ret = SkeepData(); if (ret != HRESULT.S_OK) return ret; } if (packCRCsDefined.isEmpty()) { packCRCsDefined.Reserve(numPackStreams); packCRCsDefined.clear(); packCRCs.Reserve(numPackStreams); packCRCs.clear(); for(int i = 0; i < numPackStreams; i++) { packCRCsDefined.add(false); packCRCs.add(0); } } return HRESULT.S_OK; } int ReadUnPackInfo( ObjectVector<ByteBuffer> dataVector, ObjectVector<Folder> folders) throws IOException { int ret = WaitAttribute(NID.kFolder); if (ret != HRESULT.S_OK) return ret; int numFolders = ReadNum(); { StreamSwitch streamSwitch = new StreamSwitch(); ret = streamSwitch.Set(this, dataVector); if (ret != HRESULT.S_OK) return ret; folders.clear(); folders.Reserve(numFolders); for(int i = 0; i < numFolders; i++) { folders.add(new Folder()); ret = GetNextFolderItem(folders.Back()); if (ret != HRESULT.S_OK) { streamSwitch.close(); return ret; } } streamSwitch.close(); } ret = WaitAttribute(NID.kCodersUnPackSize); if (ret != HRESULT.S_OK) return ret; for(int i = 0; i < numFolders; i++) { Folder folder = folders.get(i); int numOutStreams = folder.GetNumOutStreams(); folder.UnPackSizes.Reserve(numOutStreams); for(int j = 0; j < numOutStreams; j++) { long unPackSize = ReadNumber(); folder.UnPackSizes.add(unPackSize); } } for (;;) { long type = ReadID(); if (type == NID.kEnd) return HRESULT.S_OK; if (type == NID.kCRC) { BoolVector crcsDefined = new BoolVector(); IntVector crcs = new IntVector(); ret = ReadHashDigests(numFolders, crcsDefined, crcs); if (ret != HRESULT.S_OK) return ret; for(int i = 0; i < numFolders; i++) { Folder folder = folders.get(i); folder.UnPackCRCDefined = crcsDefined.get(i); folder.UnPackCRC = crcs.get(i); } continue; } ret = SkeepData(); if (ret != HRESULT.S_OK) return ret; } } int ReadSubStreamsInfo( ObjectVector<Folder> folders, IntVector numUnPackStreamsInFolders, LongVector unPackSizes, BoolVector digestsDefined, IntVector digests) throws IOException { numUnPackStreamsInFolders.clear(); numUnPackStreamsInFolders.Reserve(folders.size()); long type; for (;;) { type = ReadID(); if (type == NID.kNumUnPackStream) { for(int i = 0; i < folders.size(); i++) { int value = ReadNum(); numUnPackStreamsInFolders.add(value); } continue; } if (type == NID.kCRC || type == NID.kSize) break; if (type == NID.kEnd) break; int ret = SkeepData(); if (ret != HRESULT.S_OK) return ret; } if (numUnPackStreamsInFolders.isEmpty()) for(int i = 0; i < folders.size(); i++) numUnPackStreamsInFolders.add(1); for(int i = 0; i < numUnPackStreamsInFolders.size(); i++) { // v3.13 incorrectly worked with empty folders // v4.07: we check that folder is empty int numSubstreams = numUnPackStreamsInFolders.get(i); if (numSubstreams == 0) continue; long sum = 0; for (int j = 1; j < numSubstreams; j++) { long size; if (type == NID.kSize) { size = ReadNumber(); unPackSizes.add(size); sum += size; } } unPackSizes.add(folders.get(i).GetUnPackSize() - sum); } if (type == NID.kSize) { type = ReadID(); } int numDigests = 0; int numDigestsTotal = 0; for(int i = 0; i < folders.size(); i++) { int numSubstreams = numUnPackStreamsInFolders.get(i); if (numSubstreams != 1 || !folders.get(i).UnPackCRCDefined) numDigests += numSubstreams; numDigestsTotal += numSubstreams; } for (;;) { if (type == NID.kCRC) { BoolVector digestsDefined2 = new BoolVector(); IntVector digests2 = new IntVector(); int ret = ReadHashDigests(numDigests, digestsDefined2, digests2); if (ret != HRESULT.S_OK) return ret; int digestIndex = 0; for (int i = 0; i < folders.size(); i++) { int numSubstreams = numUnPackStreamsInFolders.get(i); Folder folder = folders.get(i); if (numSubstreams == 1 && folder.UnPackCRCDefined) { digestsDefined.add(true); digests.add(folder.UnPackCRC); } else for (int j = 0; j < numSubstreams; j++, digestIndex++) { digestsDefined.add(digestsDefined2.get(digestIndex)); digests.add(digests2.get(digestIndex)); } } } else if (type == NID.kEnd) { if (digestsDefined.isEmpty()) { digestsDefined.clear(); digests.clear(); for (int i = 0; i < numDigestsTotal; i++) { digestsDefined.add(false); digests.add(0); } } return HRESULT.S_OK; } else { int ret = SkeepData(); if (ret != HRESULT.S_OK) return ret; } type = ReadID(); } } static final long SECS_BETWEEN_EPOCHS = 11644473600L; static final long SECS_TO_100NS = 10000000L; /* 10^7 */ static long FileTimeToLong(int dwHighDateTime, int dwLowDateTime) { // The FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1 long tm = dwHighDateTime; tm <<=32; tm |= (dwLowDateTime & 0xFFFFFFFFL); return (tm - (SECS_BETWEEN_EPOCHS * SECS_TO_100NS)) / (10000L); /* now convert to milliseconds */ } int ReadTime(ObjectVector<ByteBuffer> dataVector, ObjectVector<FileItem> files, long type) throws IOException { BoolVector boolVector = new BoolVector(); int ret = ReadBoolVector2(files.size(), boolVector); if (ret != HRESULT.S_OK) return ret; StreamSwitch streamSwitch = new StreamSwitch(); ret = streamSwitch.Set(this, dataVector); if (ret != HRESULT.S_OK) { streamSwitch.close(); return ret; } for(int i = 0; i < files.size(); i++) { FileItem file = files.get(i); int low = 0; int high = 0; boolean defined = boolVector.get(i); if (defined) { low = ReadUInt32(); high = ReadUInt32(); } switch((int)type) { /*case NID.kCreationTime: // file.IsCreationTimeDefined = defined; if (defined) file.CreationTime = FileTimeToLong(high,low); break;*/ case NID.kLastWriteTime: // file.IsLastWriteTimeDefined = defined; if (defined) file.LastWriteTime = FileTimeToLong(high,low); break; /*case NID.kLastAccessTime: // file.IsLastAccessTimeDefined = defined; if (defined) file.LastAccessTime = FileTimeToLong(high,low); break;*/ } } streamSwitch.close(); return HRESULT.S_OK; } int ReadAndDecodePackedStreams(long baseOffset, long [] dataOffset, ObjectVector<ByteBuffer> dataVector // CObjectVector<CByteBuffer> &dataVector ) throws IOException { LongVector packSizes = new LongVector(); // CRecordVector<UInt64> packSizes; BoolVector packCRCsDefined = new BoolVector(); // CRecordVector<bool> packCRCsDefined; IntVector packCRCs = new IntVector(); // CRecordVector<UInt32> packCRCs; ObjectVector<Folder> folders = new ObjectVector<>(); IntVector numUnPackStreamsInFolders = new IntVector(); LongVector unPackSizes = new LongVector(); BoolVector digestsDefined = new BoolVector(); IntVector digests = new IntVector(); /*int ret =*/ ReadStreamsInfo(null, dataOffset, packSizes, packCRCsDefined, packCRCs, folders, numUnPackStreamsInFolders, unPackSizes, digestsDefined, digests); // database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; int packIndex = 0; Decoder decoder = new Decoder(false); // _ST_MODE long dataStartPos = baseOffset + dataOffset[0]; for(int i = 0; i < folders.size(); i++) { Folder folder = folders.get(i); // const CFolder &folder = folders[i]; dataVector.add(new ByteBuffer()); ByteBuffer data = dataVector.Back(); long unPackSize = folder.GetUnPackSize(); if (unPackSize > InArchive.kNumMax) return HRESULT.E_FAIL; if (unPackSize > 0xFFFFFFFFL) return HRESULT.E_FAIL; data.SetCapacity((int)unPackSize); org.j7zip.SevenZip.Common.SequentialOutStreamImp2 outStreamSpec = new org.j7zip.SevenZip.Common.SequentialOutStreamImp2(); java.io.OutputStream outStream = outStreamSpec; outStreamSpec.Init(data.data(), (int)unPackSize); int result = decoder.Decode(_stream, dataStartPos, packSizes,packIndex, // &packSizes[packIndex] folder, outStream, null // _ST_MODE , false, 1 ); if (result != HRESULT.S_OK) return result; if (folder.UnPackCRCDefined) if (!CRC.VerifyDigest(folder.UnPackCRC, data.data(), (int)unPackSize)) throw new IOException("Incorrect Header"); // CInArchiveException(CInArchiveException::kIncorrectHeader); for (int j = 0; j < folder.PackStreams.size(); j++) dataStartPos += packSizes.get(packIndex++); } return HRESULT.S_OK; } int ReadDatabase(ArchiveDatabaseEx database) throws IOException { database.Clear(); //database.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; byte [] btmp = new byte[2]; int realProcessedSize = ReadDirect(btmp, 2); if (realProcessedSize != 2) throw new IOException("Unexpected End Of Archive"); // throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); database.ArchiveInfo.ArchiveVersion_Major = btmp[0]; //database.ArchiveInfo.ArchiveVersion_Minor = btmp[1]; if (database.ArchiveInfo.ArchiveVersion_Major != kMajorVersion) throw new IOException("Unsupported Version"); CRC crc = new CRC(); int crcFromArchive = SafeReadDirectUInt32(); long nextHeaderOffset = SafeReadDirectUInt64(); long nextHeaderSize = SafeReadDirectUInt64(); int nextHeaderCRC = SafeReadDirectUInt32(); /* #ifdef FORMAT_7Z_RECOVERY ... #endif */ crc.UpdateUInt64(nextHeaderOffset); crc.UpdateUInt64(nextHeaderSize); crc.UpdateUInt32(nextHeaderCRC); database.ArchiveInfo.StartPositionAfterHeader = _position; if (crc.GetDigest() != crcFromArchive) throw new IOException("Incorrect Header"); // CInArchiveException(CInArchiveException::kIncorrectHeader); if (nextHeaderSize == 0) return HRESULT.S_OK; if (nextHeaderSize >= 0xFFFFFFFFL) return HRESULT.E_FAIL; _position = _stream.Seek(nextHeaderOffset,IInStream.STREAM_SEEK_CUR); ByteBuffer buffer2 = new ByteBuffer(); buffer2.SetCapacity((int)nextHeaderSize); // SafeReadDirect(buffer2.data(), (int)nextHeaderSize); realProcessedSize = ReadDirect(buffer2.data(), (int)nextHeaderSize); if (realProcessedSize != (int)nextHeaderSize) throw new IOException("Unexpected End Of Archive"); // throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); if (!CRC.VerifyDigest(nextHeaderCRC, buffer2.data(), (int)nextHeaderSize)) throw new IOException("Incorrect Header"); // CInArchiveException(CInArchiveException::kIncorrectHeader); StreamSwitch streamSwitch = new StreamSwitch(); streamSwitch.Set(this, buffer2); ObjectVector<ByteBuffer> dataVector = new ObjectVector<>(); // CObjectVector<CByteBuffer> dataVector; for (;;) { long type = ReadID(); if (type == NID.kHeader) break; if (type != NID.kEncodedHeader) throw new IOException("Incorrect Header"); // CInArchiveException(CInArchiveException::kIncorrectHeader); long [] ltmp = new long[1]; ltmp[0] = database.ArchiveInfo.DataStartPosition2; int result = ReadAndDecodePackedStreams( database.ArchiveInfo.StartPositionAfterHeader, ltmp, // database.ArchiveInfo.DataStartPosition2, dataVector); if (result != HRESULT.S_OK) return result; database.ArchiveInfo.DataStartPosition2 = ltmp[0]; if (dataVector.size() == 0) return HRESULT.S_OK; if (dataVector.size() > 1) throw new IOException("Incorrect Header"); // CInArchiveException(CInArchiveException::kIncorrectHeader); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.get(0)); // dataVector.Front() } streamSwitch.close(); return ReadHeader(database); } int ReadHeader(ArchiveDatabaseEx database) throws IOException { long type = ReadID(); if (type == NID.kArchiveProperties) { int ret = ReadArchiveProperties(database.ArchiveInfo); if (ret != HRESULT.S_OK) return ret; type = ReadID(); } ObjectVector<ByteBuffer> dataVector = new ObjectVector<>(); if (type == NID.kAdditionalStreamsInfo) { long [] ltmp = new long[1]; ltmp[0] = database.ArchiveInfo.DataStartPosition2; int result = ReadAndDecodePackedStreams( database.ArchiveInfo.StartPositionAfterHeader, ltmp, // database.ArchiveInfo.DataStartPosition2, dataVector); if (result != HRESULT.S_OK) return result; database.ArchiveInfo.DataStartPosition2 = ltmp[0]; database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } LongVector unPackSizes = new LongVector(); BoolVector digestsDefined = new BoolVector(); IntVector digests = new IntVector(); if (type == NID.kMainStreamsInfo) { long [] ltmp = new long[1]; ltmp[0] = database.ArchiveInfo.DataStartPosition; int result = ReadStreamsInfo(dataVector, ltmp, // database.ArchiveInfo.DataStartPosition, database.PackSizes, database.PackCRCsDefined, database.PackCRCs, database.Folders, database.NumUnPackStreamsVector, unPackSizes, digestsDefined, digests); if (result != HRESULT.S_OK) return result; database.ArchiveInfo.DataStartPosition = ltmp[0]; database.ArchiveInfo.DataStartPosition += database.ArchiveInfo.StartPositionAfterHeader; type = ReadID(); } else { for(int i = 0; i < database.Folders.size(); i++) { database.NumUnPackStreamsVector.add(1); Folder folder = database.Folders.get(i); unPackSizes.add(folder.GetUnPackSize()); digestsDefined.add(folder.UnPackCRCDefined); digests.add(folder.UnPackCRC); } } database.Files.clear(); if (type == NID.kEnd) return HRESULT.S_OK; if (type != NID.kFilesInfo) throw new IOException("Incorrect Header"); // throw CInArchiveException(CInArchiveException::kIncorrectHeader); int numFiles = ReadNum(); database.Files.Reserve(numFiles); for(int i = 0; i < numFiles; i++) database.Files.add(new FileItem()); database.ArchiveInfo.FileInfoPopIDs.add(NID.kSize); if (!database.PackSizes.isEmpty()) database.ArchiveInfo.FileInfoPopIDs.add(NID.kPackInfo); if (numFiles > 0 && !digests.isEmpty()) database.ArchiveInfo.FileInfoPopIDs.add(NID.kCRC); BoolVector emptyStreamVector = new BoolVector(); emptyStreamVector.Reserve(numFiles); for(int i = 0; i < numFiles; i++) emptyStreamVector.add(false); BoolVector emptyFileVector = new BoolVector(); BoolVector antiFileVector = new BoolVector(); int numEmptyStreams = 0; // int sizePrev = -1; // int posPrev = 0; for (;;) { type = ReadID(); if (type == NID.kEnd) break; long size = ReadNumber(); // sizePrev = size; // posPrev = _inByteBack->GetProcessedSize(); database.ArchiveInfo.FileInfoPopIDs.add(type); switch((int)type) { case NID.kName: { StreamSwitch streamSwitch = new StreamSwitch(); int result = streamSwitch.Set(this, dataVector); if (result != HRESULT.S_OK) return result; result = ReadFileNames(database.Files); streamSwitch.close(); if (result != HRESULT.S_OK) return result; break; } case NID.kWinAttributes: { BoolVector boolVector = new BoolVector(); int result = ReadBoolVector2(database.Files.size(), boolVector); if (result != HRESULT.S_OK) return result; StreamSwitch streamSwitch = new StreamSwitch(); result = streamSwitch.Set(this, dataVector); if (result != HRESULT.S_OK) return result; for(int i = 0; i < numFiles; i++) { FileItem file = database.Files.get(i); file.AreAttributesDefined = boolVector.get(i); if (file.AreAttributesDefined) { file.Attributes = ReadUInt32(); } } streamSwitch.close(); break; } case NID.kStartPos: { BoolVector boolVector = new BoolVector(); int result = ReadBoolVector2(database.Files.size(), boolVector); if (result != HRESULT.S_OK) return result; StreamSwitch streamSwitch = new StreamSwitch(); result = streamSwitch.Set(this, dataVector); if (result != HRESULT.S_OK) return result; for(int i = 0; i < numFiles; i++) { FileItem file = database.Files.get(i); file.IsStartPosDefined = boolVector.get(i); if (file.IsStartPosDefined) { file.StartPos = ReadUInt64(); } } streamSwitch.close(); break; } case NID.kEmptyStream: { int result = ReadBoolVector(numFiles, emptyStreamVector); if (result != HRESULT.S_OK) return result; for (int i = 0; i < emptyStreamVector.size(); i++) if (emptyStreamVector.get(i)) numEmptyStreams++; emptyFileVector.Reserve(numEmptyStreams); antiFileVector.Reserve(numEmptyStreams); for (int i = 0; i < numEmptyStreams; i++) { emptyFileVector.add(false); antiFileVector.add(false); } break; } case NID.kEmptyFile: { int result = ReadBoolVector(numEmptyStreams, emptyFileVector); if (result != HRESULT.S_OK) return result; break; } case NID.kAnti: { int result = ReadBoolVector(numEmptyStreams, antiFileVector); if (result != HRESULT.S_OK) return result; break; } case NID.kCreationTime: case NID.kLastWriteTime: case NID.kLastAccessTime: { int result = ReadTime(dataVector, database.Files, type); if (result != HRESULT.S_OK) return result; break; } default: { database.ArchiveInfo.FileInfoPopIDs.DeleteBack(); int result = SkeepData(size); if (result != HRESULT.S_OK) return result; } } } int emptyFileIndex = 0; int sizeIndex = 0; for(int i = 0; i < numFiles; i++) { FileItem file = database.Files.get(i); file.HasStream = !emptyStreamVector.get(i); if(file.HasStream) { file.IsDirectory = false; file.IsAnti = false; file.UnPackSize = unPackSizes.get(sizeIndex); file.FileCRC = digests.get(sizeIndex); file.IsFileCRCDefined = digestsDefined.get(sizeIndex); sizeIndex++; } else { file.IsDirectory = !emptyFileVector.get(emptyFileIndex); file.IsAnti = antiFileVector.get(emptyFileIndex); emptyFileIndex++; file.UnPackSize = 0; file.IsFileCRCDefined = false; } } return HRESULT.S_OK; } }