/*
* 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 < centralDirEntry
- 1
- 2
- 3
- 4
- 5
- 6
前往页