1119 lines
38 KiB
Java
1119 lines
38 KiB
Java
/*
|
|
* Copyright 2010 Srikanth Reddy Lingala
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package net.lingala.zip4j.core;
|
|
|
|
import java.io.IOException;
|
|
import java.io.RandomAccessFile;
|
|
import java.util.ArrayList;
|
|
|
|
import net.lingala.zip4j.exception.ZipException;
|
|
import net.lingala.zip4j.exception.ZipExceptionConstants;
|
|
import net.lingala.zip4j.model.AESExtraDataRecord;
|
|
import net.lingala.zip4j.model.CentralDirectory;
|
|
import net.lingala.zip4j.model.DigitalSignature;
|
|
import net.lingala.zip4j.model.EndCentralDirRecord;
|
|
import net.lingala.zip4j.model.ExtraDataRecord;
|
|
import net.lingala.zip4j.model.FileHeader;
|
|
import net.lingala.zip4j.model.LocalFileHeader;
|
|
import net.lingala.zip4j.model.Zip64EndCentralDirLocator;
|
|
import net.lingala.zip4j.model.Zip64EndCentralDirRecord;
|
|
import net.lingala.zip4j.model.Zip64ExtendedInfo;
|
|
import net.lingala.zip4j.model.ZipModel;
|
|
import net.lingala.zip4j.util.InternalZipConstants;
|
|
import net.lingala.zip4j.util.Raw;
|
|
import net.lingala.zip4j.util.Zip4jConstants;
|
|
import net.lingala.zip4j.util.Zip4jUtil;
|
|
|
|
/**
|
|
* Helper class to read header information for the zip file
|
|
*
|
|
*/
|
|
public class HeaderReader {
|
|
|
|
private RandomAccessFile zip4jRaf = null;
|
|
private ZipModel zipModel;
|
|
|
|
/**
|
|
* Creates a new HeaderReader object with the given input stream
|
|
* @param zip4jRaf
|
|
*/
|
|
public HeaderReader(RandomAccessFile zip4jRaf) {
|
|
this.zip4jRaf = zip4jRaf;
|
|
}
|
|
|
|
/**
|
|
* Reads all the header information for the zip file.
|
|
* <br><br><b>Note:</b> This method does not read local file header information
|
|
* @return {@link ZipModel}
|
|
* @throws ZipException
|
|
*/
|
|
public ZipModel readAllHeaders() throws ZipException {
|
|
return readAllHeaders(null);
|
|
}
|
|
|
|
/**
|
|
* Reads all the header information for the zip file. File names are read with
|
|
* input charset name. If this parameter is null, default system charset is used.
|
|
* <br><br><b>Note:</b> This method does not read local file header information
|
|
* @return {@link ZipModel}
|
|
* @throws ZipException
|
|
*/
|
|
public ZipModel readAllHeaders(String fileNameCharset) throws ZipException {
|
|
zipModel = new ZipModel();
|
|
zipModel.setFileNameCharset(fileNameCharset);
|
|
zipModel.setEndCentralDirRecord(readEndOfCentralDirectoryRecord());
|
|
|
|
// If file is Zip64 format, then Zip64 headers have to be read before
|
|
// reading central directory
|
|
zipModel.setZip64EndCentralDirLocator(readZip64EndCentralDirLocator());
|
|
|
|
if (zipModel.isZip64Format()) {
|
|
zipModel.setZip64EndCentralDirRecord(readZip64EndCentralDirRec());
|
|
if(zipModel.getZip64EndCentralDirRecord() != null &&
|
|
zipModel.getZip64EndCentralDirRecord().getNoOfThisDisk() > 0){
|
|
zipModel.setSplitArchive(true);
|
|
} else {
|
|
zipModel.setSplitArchive(false);
|
|
}
|
|
}
|
|
|
|
zipModel.setCentralDirectory(readCentralDirectory());
|
|
//zipModel.setLocalFileHeaderList(readLocalFileHeaders()); //Donot read local headers now.
|
|
return zipModel;
|
|
}
|
|
|
|
/**
|
|
* Reads end of central directory record
|
|
* @return {@link EndCentralDirRecord}
|
|
* @throws ZipException
|
|
*/
|
|
private EndCentralDirRecord readEndOfCentralDirectoryRecord() throws ZipException {
|
|
|
|
if (zip4jRaf == null) {
|
|
throw new ZipException("random access file was null", ZipExceptionConstants.randomAccessFileNull);
|
|
}
|
|
|
|
try {
|
|
byte[] ebs = new byte[4];
|
|
long pos = zip4jRaf.length() - InternalZipConstants.ENDHDR;
|
|
|
|
EndCentralDirRecord endCentralDirRecord = new EndCentralDirRecord();
|
|
int counter = 0;
|
|
do {
|
|
zip4jRaf.seek(pos--);
|
|
counter++;
|
|
} while ((Raw.readLeInt(zip4jRaf, ebs) != InternalZipConstants.ENDSIG) && counter <= 3000);
|
|
|
|
if ((Raw.readIntLittleEndian(ebs, 0) != InternalZipConstants.ENDSIG)) {
|
|
throw new ZipException("zip headers not found. probably not a zip file");
|
|
}
|
|
byte[] intBuff = new byte[4];
|
|
byte[] shortBuff = new byte[2];
|
|
|
|
//End of central record signature
|
|
endCentralDirRecord.setSignature(InternalZipConstants.ENDSIG);
|
|
|
|
//number of this disk
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
endCentralDirRecord.setNoOfThisDisk(Raw.readShortLittleEndian(shortBuff, 0));
|
|
|
|
//number of the disk with the start of the central directory
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
endCentralDirRecord.setNoOfThisDiskStartOfCentralDir(Raw.readShortLittleEndian(shortBuff, 0));
|
|
|
|
//total number of entries in the central directory on this disk
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
endCentralDirRecord.setTotNoOfEntriesInCentralDirOnThisDisk(Raw.readShortLittleEndian(shortBuff, 0));
|
|
|
|
//total number of entries in the central directory
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
endCentralDirRecord.setTotNoOfEntriesInCentralDir(Raw.readShortLittleEndian(shortBuff, 0));
|
|
|
|
//size of the central directory
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
endCentralDirRecord.setSizeOfCentralDir(Raw.readIntLittleEndian(intBuff, 0));
|
|
|
|
//offset of start of central directory with respect to the starting disk number
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
byte[] longBuff = getLongByteFromIntByte(intBuff);
|
|
endCentralDirRecord.setOffsetOfStartOfCentralDir(Raw.readLongLittleEndian(longBuff, 0));
|
|
|
|
//.ZIP file comment length
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
int commentLength = Raw.readShortLittleEndian(shortBuff, 0);
|
|
endCentralDirRecord.setCommentLength(commentLength);
|
|
|
|
//.ZIP file comment
|
|
if (commentLength > 0) {
|
|
byte[] commentBuf = new byte[commentLength];
|
|
readIntoBuff(zip4jRaf, commentBuf);
|
|
endCentralDirRecord.setComment(new String(commentBuf));
|
|
endCentralDirRecord.setCommentBytes(commentBuf);
|
|
} else {
|
|
endCentralDirRecord.setComment(null);
|
|
}
|
|
|
|
int diskNumber = endCentralDirRecord.getNoOfThisDisk();
|
|
if (diskNumber > 0) {
|
|
zipModel.setSplitArchive(true);
|
|
} else {
|
|
zipModel.setSplitArchive(false);
|
|
}
|
|
|
|
return endCentralDirRecord;
|
|
} catch (IOException e) {
|
|
throw new ZipException("Probably not a zip file or a corrupted zip file", e, ZipExceptionConstants.notZipFile);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads central directory information for the zip file
|
|
* @return {@link CentralDirectory}
|
|
* @throws ZipException
|
|
*/
|
|
private CentralDirectory readCentralDirectory() throws ZipException {
|
|
|
|
if (zip4jRaf == null) {
|
|
throw new ZipException("random access file was null", ZipExceptionConstants.randomAccessFileNull);
|
|
}
|
|
|
|
if (zipModel.getEndCentralDirRecord() == null) {
|
|
throw new ZipException("EndCentralRecord was null, maybe a corrupt zip file");
|
|
}
|
|
|
|
try {
|
|
CentralDirectory centralDirectory = new CentralDirectory();
|
|
ArrayList fileHeaderList = new ArrayList();
|
|
|
|
EndCentralDirRecord endCentralDirRecord = zipModel.getEndCentralDirRecord();
|
|
long offSetStartCentralDir = endCentralDirRecord.getOffsetOfStartOfCentralDir();
|
|
int centralDirEntryCount = endCentralDirRecord.getTotNoOfEntriesInCentralDir();
|
|
|
|
if (zipModel.isZip64Format()) {
|
|
offSetStartCentralDir = zipModel.getZip64EndCentralDirRecord().getOffsetStartCenDirWRTStartDiskNo();
|
|
centralDirEntryCount = (int)zipModel.getZip64EndCentralDirRecord().getTotNoOfEntriesInCentralDir();
|
|
}
|
|
|
|
zip4jRaf.seek(offSetStartCentralDir);
|
|
|
|
byte[] intBuff = new byte[4];
|
|
byte[] shortBuff = new byte[2];
|
|
byte[] longBuff = new byte[8];
|
|
|
|
for (int i = 0; i < centralDirEntryCount; i++) {
|
|
FileHeader fileHeader = new FileHeader();
|
|
|
|
//FileHeader Signature
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
int signature = Raw.readIntLittleEndian(intBuff, 0);
|
|
if (signature != InternalZipConstants.CENSIG) {
|
|
throw new ZipException("Expected central directory entry not found (#" + (i + 1) + ")");
|
|
}
|
|
fileHeader.setSignature(signature);
|
|
|
|
//version made by
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
fileHeader.setVersionMadeBy(Raw.readShortLittleEndian(shortBuff, 0));
|
|
|
|
//version needed to extract
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
fileHeader.setVersionNeededToExtract(Raw.readShortLittleEndian(shortBuff, 0));
|
|
|
|
//general purpose bit flag
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
fileHeader.setFileNameUTF8Encoded((Raw.readShortLittleEndian(shortBuff, 0) & InternalZipConstants.UFT8_NAMES_FLAG) != 0);
|
|
int firstByte = shortBuff[0];
|
|
int result = firstByte & 1;
|
|
if (result != 0) {
|
|
fileHeader.setEncrypted(true);
|
|
}
|
|
fileHeader.setGeneralPurposeFlag((byte[])shortBuff.clone());
|
|
|
|
//Check if data descriptor exists for local file header
|
|
fileHeader.setDataDescriptorExists(firstByte>>3 == 1);
|
|
|
|
//compression method
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
fileHeader.setCompressionMethod(Raw.readShortLittleEndian(shortBuff, 0));
|
|
|
|
//last mod file time
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
fileHeader.setLastModFileTime(Raw.readIntLittleEndian(intBuff, 0));
|
|
|
|
//crc-32
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
fileHeader.setCrc32(Raw.readIntLittleEndian(intBuff, 0));
|
|
fileHeader.setCrcBuff((byte[])intBuff.clone());
|
|
|
|
//compressed size
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
longBuff = getLongByteFromIntByte(intBuff);
|
|
fileHeader.setCompressedSize(Raw.readLongLittleEndian(longBuff, 0));
|
|
|
|
//uncompressed size
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
longBuff = getLongByteFromIntByte(intBuff);
|
|
fileHeader.setUncompressedSize(Raw.readLongLittleEndian(longBuff, 0));
|
|
|
|
//file name length
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
int fileNameLength = Raw.readShortLittleEndian(shortBuff, 0);
|
|
fileHeader.setFileNameLength(fileNameLength);
|
|
|
|
//extra field length
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
int extraFieldLength = Raw.readShortLittleEndian(shortBuff, 0);
|
|
fileHeader.setExtraFieldLength(extraFieldLength);
|
|
|
|
//file comment length
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
int fileCommentLength = Raw.readShortLittleEndian(shortBuff, 0);
|
|
fileHeader.setFileComment(new String(shortBuff));
|
|
|
|
//disk number start
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
fileHeader.setDiskNumberStart(Raw.readShortLittleEndian(shortBuff, 0));
|
|
|
|
//internal file attributes
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
fileHeader.setInternalFileAttr((byte[])shortBuff.clone());
|
|
|
|
//external file attributes
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
fileHeader.setExternalFileAttr((byte[])intBuff.clone());
|
|
|
|
//relative offset of local header
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
//Commented on 26.08.2010. Revert back if any issues
|
|
//fileHeader.setOffsetLocalHeader((Raw.readIntLittleEndian(intBuff, 0) & 0xFFFFFFFFL) + zip4jRaf.getStart());
|
|
longBuff = getLongByteFromIntByte(intBuff);
|
|
fileHeader.setOffsetLocalHeader((Raw.readLongLittleEndian(longBuff, 0) & 0xFFFFFFFFL));
|
|
|
|
if (fileNameLength > 0) {
|
|
byte[] fileNameBuf = new byte[fileNameLength];
|
|
readIntoBuff(zip4jRaf, fileNameBuf);
|
|
// Modified after user reported an issue http://www.lingala.net/zip4j/forum/index.php?topic=2.0
|
|
// String fileName = new String(fileNameBuf, "Cp850");
|
|
// Modified as per http://www.lingala.net/zip4j/forum/index.php?topic=41.0
|
|
// String fileName = Zip4jUtil.getCp850EncodedString(fileNameBuf);
|
|
|
|
String fileName = null;
|
|
|
|
if (Zip4jUtil.isStringNotNullAndNotEmpty(zipModel.getFileNameCharset())) {
|
|
fileName = new String(fileNameBuf, zipModel.getFileNameCharset());
|
|
} else {
|
|
fileName = Zip4jUtil.decodeFileName(fileNameBuf, fileHeader.isFileNameUTF8Encoded());
|
|
}
|
|
|
|
if (fileName == null) {
|
|
throw new ZipException("fileName is null when reading central directory");
|
|
}
|
|
|
|
if (fileName.indexOf(":" + System.getProperty("file.separator")) >= 0) {
|
|
fileName = fileName.substring(fileName.indexOf(":" + System.getProperty("file.separator")) + 2);
|
|
}
|
|
|
|
fileHeader.setFileName(fileName);
|
|
fileHeader.setDirectory(fileName.endsWith("/") || fileName.endsWith("\\"));
|
|
|
|
} else {
|
|
fileHeader.setFileName(null);
|
|
}
|
|
|
|
//Extra field
|
|
readAndSaveExtraDataRecord(fileHeader);
|
|
|
|
//Read Zip64 Extra data records if exists
|
|
readAndSaveZip64ExtendedInfo(fileHeader);
|
|
|
|
//Read AES Extra Data record if exists
|
|
readAndSaveAESExtraDataRecord(fileHeader);
|
|
|
|
// if (fileHeader.isEncrypted()) {
|
|
//
|
|
// if (fileHeader.getEncryptionMethod() == ZipConstants.ENC_METHOD_AES) {
|
|
// //Do nothing
|
|
// } else {
|
|
// if ((firstByte & 64) == 64) {
|
|
// //hardcoded for now
|
|
// fileHeader.setEncryptionMethod(1);
|
|
// } else {
|
|
// fileHeader.setEncryptionMethod(ZipConstants.ENC_METHOD_STANDARD);
|
|
// fileHeader.setCompressedSize(fileHeader.getCompressedSize()
|
|
// - ZipConstants.STD_DEC_HDR_SIZE);
|
|
// }
|
|
// }
|
|
//
|
|
// }
|
|
|
|
if (fileCommentLength > 0) {
|
|
byte[] fileCommentBuf = new byte[fileCommentLength];
|
|
readIntoBuff(zip4jRaf, fileCommentBuf);
|
|
fileHeader.setFileComment(new String(fileCommentBuf));
|
|
}
|
|
|
|
fileHeaderList.add(fileHeader);
|
|
}
|
|
centralDirectory.setFileHeaders(fileHeaderList);
|
|
|
|
//Digital Signature
|
|
DigitalSignature digitalSignature = new DigitalSignature();
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
int signature = Raw.readIntLittleEndian(intBuff, 0);
|
|
if (signature != InternalZipConstants.DIGSIG) {
|
|
return centralDirectory;
|
|
}
|
|
|
|
digitalSignature.setHeaderSignature(signature);
|
|
|
|
//size of data
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
int sizeOfData = Raw.readShortLittleEndian(shortBuff, 0);
|
|
digitalSignature.setSizeOfData(sizeOfData);
|
|
|
|
if (sizeOfData > 0) {
|
|
byte[] sigDataBuf = new byte[sizeOfData];
|
|
readIntoBuff(zip4jRaf, sigDataBuf);
|
|
digitalSignature.setSignatureData(new String(sigDataBuf));
|
|
}
|
|
|
|
return centralDirectory;
|
|
} catch (IOException e) {
|
|
throw new ZipException(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads extra data record and saves it in the {@link FileHeader}
|
|
* @param fileHeader
|
|
* @throws ZipException
|
|
*/
|
|
private void readAndSaveExtraDataRecord(FileHeader fileHeader) throws ZipException {
|
|
|
|
if (zip4jRaf == null) {
|
|
throw new ZipException("invalid file handler when trying to read extra data record");
|
|
}
|
|
|
|
if (fileHeader == null) {
|
|
throw new ZipException("file header is null");
|
|
}
|
|
|
|
int extraFieldLength = fileHeader.getExtraFieldLength();
|
|
if (extraFieldLength <= 0) {
|
|
return;
|
|
}
|
|
|
|
fileHeader.setExtraDataRecords(readExtraDataRecords(extraFieldLength));
|
|
|
|
}
|
|
|
|
/**
|
|
* Reads extra data record and saves it in the {@link LocalFileHeader}
|
|
* @param localFileHeader
|
|
* @throws ZipException
|
|
*/
|
|
private void readAndSaveExtraDataRecord(LocalFileHeader localFileHeader) throws ZipException {
|
|
|
|
if (zip4jRaf == null) {
|
|
throw new ZipException("invalid file handler when trying to read extra data record");
|
|
}
|
|
|
|
if (localFileHeader == null) {
|
|
throw new ZipException("file header is null");
|
|
}
|
|
|
|
int extraFieldLength = localFileHeader.getExtraFieldLength();
|
|
if (extraFieldLength <= 0) {
|
|
return;
|
|
}
|
|
|
|
localFileHeader.setExtraDataRecords(readExtraDataRecords(extraFieldLength));
|
|
|
|
}
|
|
|
|
/**
|
|
* Reads extra data records
|
|
* @param extraFieldLength
|
|
* @return ArrayList of {@link ExtraDataRecord}
|
|
* @throws ZipException
|
|
*/
|
|
private ArrayList readExtraDataRecords(int extraFieldLength) throws ZipException {
|
|
|
|
if (extraFieldLength <= 0) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
byte[] extraFieldBuf = new byte[extraFieldLength];
|
|
zip4jRaf.read(extraFieldBuf);
|
|
|
|
int counter = 0;
|
|
ArrayList extraDataList = new ArrayList();
|
|
while(counter < extraFieldLength) {
|
|
ExtraDataRecord extraDataRecord = new ExtraDataRecord();
|
|
int header = Raw.readShortLittleEndian(extraFieldBuf, counter);
|
|
extraDataRecord.setHeader(header);
|
|
counter = counter + 2;
|
|
int sizeOfRec = Raw.readShortLittleEndian(extraFieldBuf, counter);
|
|
|
|
if ((2 + sizeOfRec) > extraFieldLength) {
|
|
sizeOfRec = Raw.readShortBigEndian(extraFieldBuf, counter);
|
|
if ((2 + sizeOfRec) > extraFieldLength) {
|
|
//If this is the case, then extra data record is corrupt
|
|
//skip reading any further extra data records
|
|
break;
|
|
}
|
|
}
|
|
|
|
extraDataRecord.setSizeOfData(sizeOfRec);
|
|
counter = counter + 2;
|
|
|
|
if (sizeOfRec > 0) {
|
|
byte[] data = new byte[sizeOfRec];
|
|
System.arraycopy(extraFieldBuf, counter, data, 0, sizeOfRec);
|
|
extraDataRecord.setData(data);
|
|
}
|
|
counter = counter + sizeOfRec;
|
|
extraDataList.add(extraDataRecord);
|
|
}
|
|
if (extraDataList.size() > 0) {
|
|
return extraDataList;
|
|
} else {
|
|
return null;
|
|
}
|
|
} catch (IOException e) {
|
|
throw new ZipException(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads Zip64 End Of Central Directory Locator
|
|
* @return {@link Zip64EndCentralDirLocator}
|
|
* @throws ZipException
|
|
*/
|
|
private Zip64EndCentralDirLocator readZip64EndCentralDirLocator() throws ZipException {
|
|
|
|
if (zip4jRaf == null) {
|
|
throw new ZipException("invalid file handler when trying to read Zip64EndCentralDirLocator");
|
|
}
|
|
|
|
try {
|
|
Zip64EndCentralDirLocator zip64EndCentralDirLocator = new Zip64EndCentralDirLocator();
|
|
|
|
setFilePointerToReadZip64EndCentralDirLoc();
|
|
|
|
byte[] intBuff = new byte[4];
|
|
byte[] longBuff = new byte[8];
|
|
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
int signature = Raw.readIntLittleEndian(intBuff, 0);
|
|
if (signature == InternalZipConstants.ZIP64ENDCENDIRLOC) {
|
|
zipModel.setZip64Format(true);
|
|
zip64EndCentralDirLocator.setSignature(signature);
|
|
} else {
|
|
zipModel.setZip64Format(false);
|
|
return null;
|
|
}
|
|
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
zip64EndCentralDirLocator.setNoOfDiskStartOfZip64EndOfCentralDirRec(
|
|
Raw.readIntLittleEndian(intBuff, 0));
|
|
|
|
readIntoBuff(zip4jRaf, longBuff);
|
|
zip64EndCentralDirLocator.setOffsetZip64EndOfCentralDirRec(
|
|
Raw.readLongLittleEndian(longBuff, 0));
|
|
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
zip64EndCentralDirLocator.setTotNumberOfDiscs(Raw.readIntLittleEndian(intBuff, 0));
|
|
|
|
return zip64EndCentralDirLocator;
|
|
|
|
} catch (Exception e) {
|
|
throw new ZipException(e);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Reads Zip64 End of Central Directory Record
|
|
* @return {@link Zip64EndCentralDirRecord}
|
|
* @throws ZipException
|
|
*/
|
|
private Zip64EndCentralDirRecord readZip64EndCentralDirRec() throws ZipException {
|
|
|
|
if (zipModel.getZip64EndCentralDirLocator() == null) {
|
|
throw new ZipException("invalid zip64 end of central directory locator");
|
|
}
|
|
|
|
long offSetStartOfZip64CentralDir =
|
|
zipModel.getZip64EndCentralDirLocator().getOffsetZip64EndOfCentralDirRec();
|
|
|
|
if (offSetStartOfZip64CentralDir < 0) {
|
|
throw new ZipException("invalid offset for start of end of central directory record");
|
|
}
|
|
|
|
try {
|
|
zip4jRaf.seek(offSetStartOfZip64CentralDir);
|
|
|
|
Zip64EndCentralDirRecord zip64EndCentralDirRecord = new Zip64EndCentralDirRecord();
|
|
|
|
byte[] shortBuff = new byte[2];
|
|
byte[] intBuff = new byte[4];
|
|
byte[] longBuff = new byte[8];
|
|
|
|
//signature
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
int signature = Raw.readIntLittleEndian(intBuff, 0);
|
|
if (signature != InternalZipConstants.ZIP64ENDCENDIRREC) {
|
|
throw new ZipException("invalid signature for zip64 end of central directory record");
|
|
}
|
|
zip64EndCentralDirRecord.setSignature(signature);
|
|
|
|
//size of zip64 end of central directory record
|
|
readIntoBuff(zip4jRaf, longBuff);
|
|
zip64EndCentralDirRecord.setSizeOfZip64EndCentralDirRec(
|
|
Raw.readLongLittleEndian(longBuff, 0));
|
|
|
|
//version made by
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
zip64EndCentralDirRecord.setVersionMadeBy(Raw.readShortLittleEndian(shortBuff, 0));
|
|
|
|
//version needed to extract
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
zip64EndCentralDirRecord.setVersionNeededToExtract(Raw.readShortLittleEndian(shortBuff, 0));
|
|
|
|
//number of this disk
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
zip64EndCentralDirRecord.setNoOfThisDisk(Raw.readIntLittleEndian(intBuff, 0));
|
|
|
|
//number of the disk with the start of the central directory
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
zip64EndCentralDirRecord.setNoOfThisDiskStartOfCentralDir(
|
|
Raw.readIntLittleEndian(intBuff, 0));
|
|
|
|
//total number of entries in the central directory on this disk
|
|
readIntoBuff(zip4jRaf, longBuff);
|
|
zip64EndCentralDirRecord.setTotNoOfEntriesInCentralDirOnThisDisk(
|
|
Raw.readLongLittleEndian(longBuff, 0));
|
|
|
|
//total number of entries in the central directory
|
|
readIntoBuff(zip4jRaf, longBuff);
|
|
zip64EndCentralDirRecord.setTotNoOfEntriesInCentralDir(
|
|
Raw.readLongLittleEndian(longBuff, 0));
|
|
|
|
//size of the central directory
|
|
readIntoBuff(zip4jRaf, longBuff);
|
|
zip64EndCentralDirRecord.setSizeOfCentralDir(Raw.readLongLittleEndian(longBuff, 0));
|
|
|
|
//offset of start of central directory with respect to the starting disk number
|
|
readIntoBuff(zip4jRaf, longBuff);
|
|
zip64EndCentralDirRecord.setOffsetStartCenDirWRTStartDiskNo(
|
|
Raw.readLongLittleEndian(longBuff, 0));
|
|
|
|
//zip64 extensible data sector
|
|
//44 is the size of fixed variables in this record
|
|
long extDataSecSize = zip64EndCentralDirRecord.getSizeOfZip64EndCentralDirRec() - 44;
|
|
if (extDataSecSize > 0) {
|
|
byte[] extDataSecRecBuf = new byte[(int)extDataSecSize];
|
|
readIntoBuff(zip4jRaf, extDataSecRecBuf);
|
|
zip64EndCentralDirRecord.setExtensibleDataSector(extDataSecRecBuf);
|
|
}
|
|
|
|
return zip64EndCentralDirRecord;
|
|
|
|
} catch (IOException e) {
|
|
throw new ZipException(e);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Reads Zip64 Extended info and saves it in the {@link FileHeader}
|
|
* @param fileHeader
|
|
* @throws ZipException
|
|
*/
|
|
private void readAndSaveZip64ExtendedInfo(FileHeader fileHeader) throws ZipException {
|
|
if (fileHeader == null) {
|
|
throw new ZipException("file header is null in reading Zip64 Extended Info");
|
|
}
|
|
|
|
if (fileHeader.getExtraDataRecords() == null || fileHeader.getExtraDataRecords().size() <= 0) {
|
|
return;
|
|
}
|
|
|
|
Zip64ExtendedInfo zip64ExtendedInfo = readZip64ExtendedInfo(
|
|
fileHeader.getExtraDataRecords(),
|
|
fileHeader.getUncompressedSize(),
|
|
fileHeader.getCompressedSize(),
|
|
fileHeader.getOffsetLocalHeader(),
|
|
fileHeader.getDiskNumberStart());
|
|
|
|
if (zip64ExtendedInfo != null) {
|
|
fileHeader.setZip64ExtendedInfo(zip64ExtendedInfo);
|
|
if (zip64ExtendedInfo.getUnCompressedSize() != -1)
|
|
fileHeader.setUncompressedSize(zip64ExtendedInfo.getUnCompressedSize());
|
|
|
|
if (zip64ExtendedInfo.getCompressedSize() != -1)
|
|
fileHeader.setCompressedSize(zip64ExtendedInfo.getCompressedSize());
|
|
|
|
if (zip64ExtendedInfo.getOffsetLocalHeader() != -1)
|
|
fileHeader.setOffsetLocalHeader(zip64ExtendedInfo.getOffsetLocalHeader());
|
|
|
|
if (zip64ExtendedInfo.getDiskNumberStart() != -1)
|
|
fileHeader.setDiskNumberStart(zip64ExtendedInfo.getDiskNumberStart());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads Zip64 Extended Info and saves it in the {@link LocalFileHeader}
|
|
* @param localFileHeader
|
|
* @throws ZipException
|
|
*/
|
|
private void readAndSaveZip64ExtendedInfo(LocalFileHeader localFileHeader) throws ZipException {
|
|
if (localFileHeader == null) {
|
|
throw new ZipException("file header is null in reading Zip64 Extended Info");
|
|
}
|
|
|
|
if (localFileHeader.getExtraDataRecords() == null || localFileHeader.getExtraDataRecords().size() <= 0) {
|
|
return;
|
|
}
|
|
|
|
Zip64ExtendedInfo zip64ExtendedInfo = readZip64ExtendedInfo(
|
|
localFileHeader.getExtraDataRecords(),
|
|
localFileHeader.getUncompressedSize(),
|
|
localFileHeader.getCompressedSize(),
|
|
-1, -1);
|
|
|
|
if (zip64ExtendedInfo != null) {
|
|
localFileHeader.setZip64ExtendedInfo(zip64ExtendedInfo);
|
|
|
|
if (zip64ExtendedInfo.getUnCompressedSize() != -1)
|
|
localFileHeader.setUncompressedSize(zip64ExtendedInfo.getUnCompressedSize());
|
|
|
|
if (zip64ExtendedInfo.getCompressedSize() != -1)
|
|
localFileHeader.setCompressedSize(zip64ExtendedInfo.getCompressedSize());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads Zip64 Extended Info
|
|
* @param extraDataRecords
|
|
* @param unCompressedSize
|
|
* @param compressedSize
|
|
* @param offsetLocalHeader
|
|
* @param diskNumberStart
|
|
* @return {@link Zip64ExtendedInfo}
|
|
* @throws ZipException
|
|
*/
|
|
private Zip64ExtendedInfo readZip64ExtendedInfo(
|
|
ArrayList extraDataRecords,
|
|
long unCompressedSize,
|
|
long compressedSize,
|
|
long offsetLocalHeader,
|
|
int diskNumberStart) throws ZipException {
|
|
|
|
for (int i = 0; i < extraDataRecords.size(); i++) {
|
|
ExtraDataRecord extraDataRecord = (ExtraDataRecord)extraDataRecords.get(i);
|
|
if (extraDataRecord == null) {
|
|
continue;
|
|
}
|
|
|
|
if (extraDataRecord.getHeader() == 0x0001) {
|
|
|
|
Zip64ExtendedInfo zip64ExtendedInfo = new Zip64ExtendedInfo();
|
|
|
|
byte[] byteBuff = extraDataRecord.getData();
|
|
|
|
if (extraDataRecord.getSizeOfData() <= 0) {
|
|
break;
|
|
}
|
|
byte[] longByteBuff = new byte[8];
|
|
byte[] intByteBuff = new byte[4];
|
|
int counter = 0;
|
|
boolean valueAdded = false;
|
|
|
|
if (((unCompressedSize & 0xFFFF) == 0xFFFF) && counter < extraDataRecord.getSizeOfData()) {
|
|
System.arraycopy(byteBuff, counter, longByteBuff, 0, 8);
|
|
long val = Raw.readLongLittleEndian(longByteBuff, 0);
|
|
zip64ExtendedInfo.setUnCompressedSize(val);
|
|
counter += 8;
|
|
valueAdded = true;
|
|
}
|
|
|
|
if (((compressedSize & 0xFFFF) == 0xFFFF) && counter < extraDataRecord.getSizeOfData()) {
|
|
System.arraycopy(byteBuff, counter, longByteBuff, 0, 8);
|
|
long val = Raw.readLongLittleEndian(longByteBuff, 0);
|
|
zip64ExtendedInfo.setCompressedSize(val);
|
|
counter += 8;
|
|
valueAdded = true;
|
|
}
|
|
|
|
if (((offsetLocalHeader & 0xFFFF) == 0xFFFF) && counter < extraDataRecord.getSizeOfData()) {
|
|
System.arraycopy(byteBuff, counter, longByteBuff, 0, 8);
|
|
long val = Raw.readLongLittleEndian(longByteBuff, 0);
|
|
zip64ExtendedInfo.setOffsetLocalHeader(val);
|
|
counter += 8;
|
|
valueAdded = true;
|
|
}
|
|
|
|
if (((diskNumberStart & 0xFFFF) == 0xFFFF) && counter < extraDataRecord.getSizeOfData()) {
|
|
System.arraycopy(byteBuff, counter, intByteBuff, 0, 4);
|
|
int val = Raw.readIntLittleEndian(intByteBuff, 0);
|
|
zip64ExtendedInfo.setDiskNumberStart(val);
|
|
counter += 8;
|
|
valueAdded = true;
|
|
}
|
|
|
|
if (valueAdded) {
|
|
return zip64ExtendedInfo;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Sets the current random access file pointer at the start of signature
|
|
* of the zip64 end of central directory record
|
|
* @throws ZipException
|
|
*/
|
|
private void setFilePointerToReadZip64EndCentralDirLoc() throws ZipException {
|
|
try {
|
|
byte[] ebs = new byte[4];
|
|
long pos = zip4jRaf.length() - InternalZipConstants.ENDHDR;
|
|
|
|
do {
|
|
zip4jRaf.seek(pos--);
|
|
} while (Raw.readLeInt(zip4jRaf, ebs) != InternalZipConstants.ENDSIG);
|
|
|
|
// Now the file pointer is at the end of signature of Central Dir Rec
|
|
// Seek back with the following values
|
|
// 4 -> end of central dir signature
|
|
// 4 -> total number of disks
|
|
// 8 -> relative offset of the zip64 end of central directory record
|
|
// 4 -> number of the disk with the start of the zip64 end of central directory
|
|
// 4 -> zip64 end of central dir locator signature
|
|
// Refer to Appnote for more information
|
|
//TODO: Donot harcorde these values. Make use of ZipConstants
|
|
zip4jRaf.seek(zip4jRaf.getFilePointer() - 4 - 4 - 8 - 4 - 4);
|
|
} catch (IOException e) {
|
|
throw new ZipException(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads local file header for the given file header
|
|
* @param fileHeader
|
|
* @return {@link LocalFileHeader}
|
|
* @throws ZipException
|
|
*/
|
|
public LocalFileHeader readLocalFileHeader(FileHeader fileHeader) throws ZipException {
|
|
if (fileHeader == null || zip4jRaf == null) {
|
|
throw new ZipException("invalid read parameters for local header");
|
|
}
|
|
|
|
long locHdrOffset = fileHeader.getOffsetLocalHeader();
|
|
|
|
if (fileHeader.getZip64ExtendedInfo() != null) {
|
|
Zip64ExtendedInfo zip64ExtendedInfo = fileHeader.getZip64ExtendedInfo();
|
|
if (zip64ExtendedInfo.getOffsetLocalHeader() > 0) {
|
|
locHdrOffset = fileHeader.getOffsetLocalHeader();
|
|
}
|
|
}
|
|
|
|
if (locHdrOffset < 0) {
|
|
throw new ZipException("invalid local header offset");
|
|
}
|
|
|
|
try {
|
|
zip4jRaf.seek(locHdrOffset);
|
|
|
|
int length = 0;
|
|
LocalFileHeader localFileHeader = new LocalFileHeader();
|
|
|
|
byte[] shortBuff = new byte[2];
|
|
byte[] intBuff = new byte[4];
|
|
byte[] longBuff = new byte[8];
|
|
|
|
//signature
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
int sig = Raw.readIntLittleEndian(intBuff, 0);
|
|
if (sig != InternalZipConstants.LOCSIG) {
|
|
throw new ZipException("invalid local header signature for file: " + fileHeader.getFileName());
|
|
}
|
|
localFileHeader.setSignature(sig);
|
|
length += 4;
|
|
|
|
//version needed to extract
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
localFileHeader.setVersionNeededToExtract(Raw.readShortLittleEndian(shortBuff, 0));
|
|
length += 2;
|
|
|
|
//general purpose bit flag
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
localFileHeader.setFileNameUTF8Encoded((Raw.readShortLittleEndian(shortBuff, 0) & InternalZipConstants.UFT8_NAMES_FLAG) != 0);
|
|
int firstByte = shortBuff[0];
|
|
int result = firstByte & 1;
|
|
if (result != 0) {
|
|
localFileHeader.setEncrypted(true);
|
|
}
|
|
localFileHeader.setGeneralPurposeFlag(shortBuff);
|
|
length += 2;
|
|
|
|
//Check if data descriptor exists for local file header
|
|
String binary = Integer.toBinaryString(firstByte);
|
|
if (binary.length() >= 4)
|
|
localFileHeader.setDataDescriptorExists(binary.charAt(3) == '1');
|
|
|
|
//compression method
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
localFileHeader.setCompressionMethod(Raw.readShortLittleEndian(shortBuff, 0));
|
|
length += 2;
|
|
|
|
//last mod file time
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
localFileHeader.setLastModFileTime(Raw.readIntLittleEndian(intBuff, 0));
|
|
length += 4;
|
|
|
|
//crc-32
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
localFileHeader.setCrc32(Raw.readIntLittleEndian(intBuff, 0));
|
|
localFileHeader.setCrcBuff((byte[])intBuff.clone());
|
|
length += 4;
|
|
|
|
//compressed size
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
longBuff = getLongByteFromIntByte(intBuff);
|
|
localFileHeader.setCompressedSize(Raw.readLongLittleEndian(longBuff, 0));
|
|
length += 4;
|
|
|
|
//uncompressed size
|
|
readIntoBuff(zip4jRaf, intBuff);
|
|
longBuff = getLongByteFromIntByte(intBuff);
|
|
localFileHeader.setUncompressedSize(Raw.readLongLittleEndian(longBuff, 0));
|
|
length += 4;
|
|
|
|
//file name length
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
int fileNameLength = Raw.readShortLittleEndian(shortBuff, 0);
|
|
localFileHeader.setFileNameLength(fileNameLength);
|
|
length += 2;
|
|
|
|
//extra field length
|
|
readIntoBuff(zip4jRaf, shortBuff);
|
|
int extraFieldLength = Raw.readShortLittleEndian(shortBuff, 0);
|
|
localFileHeader.setExtraFieldLength(extraFieldLength);
|
|
length += 2;
|
|
|
|
//file name
|
|
if (fileNameLength > 0) {
|
|
byte[] fileNameBuf = new byte[fileNameLength];
|
|
readIntoBuff(zip4jRaf, fileNameBuf);
|
|
// Modified after user reported an issue http://www.lingala.net/zip4j/forum/index.php?topic=2.0
|
|
// String fileName = new String(fileNameBuf, "Cp850");
|
|
// String fileName = Zip4jUtil.getCp850EncodedString(fileNameBuf);
|
|
String fileName = Zip4jUtil.decodeFileName(fileNameBuf, localFileHeader.isFileNameUTF8Encoded());
|
|
|
|
if (fileName == null) {
|
|
throw new ZipException("file name is null, cannot assign file name to local file header");
|
|
}
|
|
|
|
if (fileName.indexOf(":" + System.getProperty("file.separator")) >= 0) {
|
|
fileName = fileName.substring(fileName.indexOf(":" + System.getProperty("file.separator")) + 2);
|
|
}
|
|
|
|
localFileHeader.setFileName(fileName);
|
|
length += fileNameLength;
|
|
} else {
|
|
localFileHeader.setFileName(null);
|
|
}
|
|
|
|
//extra field
|
|
readAndSaveExtraDataRecord(localFileHeader);
|
|
length += extraFieldLength;
|
|
|
|
localFileHeader.setOffsetStartOfData(locHdrOffset + length);
|
|
|
|
//Copy password from fileHeader to localFileHeader
|
|
localFileHeader.setPassword(fileHeader.getPassword());
|
|
|
|
readAndSaveZip64ExtendedInfo(localFileHeader);
|
|
|
|
readAndSaveAESExtraDataRecord(localFileHeader);
|
|
|
|
if (localFileHeader.isEncrypted()) {
|
|
|
|
if (localFileHeader.getEncryptionMethod() == Zip4jConstants.ENC_METHOD_AES) {
|
|
//Do nothing
|
|
} else {
|
|
if ((firstByte & 64) == 64) {
|
|
//hardcoded for now
|
|
localFileHeader.setEncryptionMethod(1);
|
|
} else {
|
|
localFileHeader.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
|
|
// localFileHeader.setCompressedSize(localFileHeader.getCompressedSize()
|
|
// - ZipConstants.STD_DEC_HDR_SIZE);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (localFileHeader.getCrc32() <= 0) {
|
|
localFileHeader.setCrc32(fileHeader.getCrc32());
|
|
localFileHeader.setCrcBuff(fileHeader.getCrcBuff());
|
|
}
|
|
|
|
if (localFileHeader.getCompressedSize() <= 0) {
|
|
localFileHeader.setCompressedSize(fileHeader.getCompressedSize());
|
|
}
|
|
|
|
if (localFileHeader.getUncompressedSize() <= 0) {
|
|
localFileHeader.setUncompressedSize(fileHeader.getUncompressedSize());
|
|
}
|
|
|
|
return localFileHeader;
|
|
} catch (IOException e) {
|
|
throw new ZipException(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads AES Extra Data Record and saves it in the {@link FileHeader}
|
|
* @param fileHeader
|
|
* @throws ZipException
|
|
*/
|
|
private void readAndSaveAESExtraDataRecord(FileHeader fileHeader) throws ZipException {
|
|
if (fileHeader == null) {
|
|
throw new ZipException("file header is null in reading Zip64 Extended Info");
|
|
}
|
|
|
|
if (fileHeader.getExtraDataRecords() == null || fileHeader.getExtraDataRecords().size() <= 0) {
|
|
return;
|
|
}
|
|
|
|
AESExtraDataRecord aesExtraDataRecord = readAESExtraDataRecord(fileHeader.getExtraDataRecords());
|
|
if (aesExtraDataRecord != null) {
|
|
fileHeader.setAesExtraDataRecord(aesExtraDataRecord);
|
|
fileHeader.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads AES Extra Data Record and saves it in the {@link LocalFileHeader}
|
|
* @param localFileHeader
|
|
* @throws ZipException
|
|
*/
|
|
private void readAndSaveAESExtraDataRecord(LocalFileHeader localFileHeader) throws ZipException {
|
|
if (localFileHeader == null) {
|
|
throw new ZipException("file header is null in reading Zip64 Extended Info");
|
|
}
|
|
|
|
if (localFileHeader.getExtraDataRecords() == null || localFileHeader.getExtraDataRecords().size() <= 0) {
|
|
return;
|
|
}
|
|
|
|
AESExtraDataRecord aesExtraDataRecord = readAESExtraDataRecord(localFileHeader.getExtraDataRecords());
|
|
if (aesExtraDataRecord != null) {
|
|
localFileHeader.setAesExtraDataRecord(aesExtraDataRecord);
|
|
localFileHeader.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads AES Extra Data Record
|
|
* @param extraDataRecords
|
|
* @return {@link AESExtraDataRecord}
|
|
* @throws ZipException
|
|
*/
|
|
private AESExtraDataRecord readAESExtraDataRecord(ArrayList extraDataRecords) throws ZipException {
|
|
|
|
if (extraDataRecords == null) {
|
|
return null;
|
|
}
|
|
|
|
for (int i = 0; i < extraDataRecords.size(); i++) {
|
|
ExtraDataRecord extraDataRecord = (ExtraDataRecord)extraDataRecords.get(i);
|
|
if (extraDataRecord == null) {
|
|
continue;
|
|
}
|
|
|
|
if (extraDataRecord.getHeader() == InternalZipConstants.AESSIG) {
|
|
|
|
if (extraDataRecord.getData() == null) {
|
|
throw new ZipException("corrput AES extra data records");
|
|
}
|
|
|
|
AESExtraDataRecord aesExtraDataRecord = new AESExtraDataRecord();
|
|
|
|
aesExtraDataRecord.setSignature(InternalZipConstants.AESSIG);
|
|
aesExtraDataRecord.setDataSize(extraDataRecord.getSizeOfData());
|
|
|
|
byte[] aesData = extraDataRecord.getData();
|
|
aesExtraDataRecord.setVersionNumber(Raw.readShortLittleEndian(aesData, 0));
|
|
byte[] vendorIDBytes = new byte[2];
|
|
System.arraycopy(aesData, 2, vendorIDBytes, 0, 2);
|
|
aesExtraDataRecord.setVendorID(new String(vendorIDBytes));
|
|
aesExtraDataRecord.setAesStrength((int)(aesData[4] & 0xFF));
|
|
aesExtraDataRecord.setCompressionMethod(Raw.readShortLittleEndian(aesData, 5));
|
|
|
|
return aesExtraDataRecord;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Reads buf length of bytes from the input stream to buf
|
|
* @param zip4jRaf
|
|
* @param buf
|
|
* @return byte array
|
|
* @throws ZipException
|
|
*/
|
|
private byte[] readIntoBuff(RandomAccessFile zip4jRaf, byte[] buf) throws ZipException {
|
|
try {
|
|
if (zip4jRaf.read(buf, 0, buf.length) != -1) {
|
|
return buf;
|
|
} else {
|
|
throw new ZipException("unexpected end of file when reading short buff");
|
|
}
|
|
} catch (IOException e) {
|
|
throw new ZipException("IOException when reading short buff", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a long byte from an int byte by appending last 4 bytes as 0's
|
|
* @param intByte
|
|
* @return byte array
|
|
* @throws ZipException
|
|
*/
|
|
private byte[] getLongByteFromIntByte(byte[] intByte) throws ZipException {
|
|
if (intByte == null) {
|
|
throw new ZipException("input parameter is null, cannot expand to 8 bytes");
|
|
}
|
|
|
|
if (intByte.length != 4) {
|
|
throw new ZipException("invalid byte length, cannot expand to 8 bytes");
|
|
}
|
|
|
|
byte[] longBuff = {intByte[0], intByte[1], intByte[2], intByte[3], 0, 0, 0, 0};
|
|
return longBuff;
|
|
}
|
|
}
|