/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 31.05.2007
*
* Source: $HeadURL$
* Last changed: $LastChangedDate$
*
* the unrar licence applies to all junrar source and binary distributions
* you are not allowed to use this source to re-create the RAR compression algorithm
*
* Here some html entities which can be used for escaping javadoc tags:
* "&": "&" or "&"
* "<": "<" or "<"
* ">": ">" or ">"
* "@": "@"
*/
package com.github.junrar.unpack;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.github.junrar.Archive;
import com.github.junrar.UnrarCallback;
import com.github.junrar.Volume;
import com.github.junrar.crc.RarCRC;
import com.github.junrar.exception.RarException;
import com.github.junrar.exception.RarException.RarExceptionType;
import com.github.junrar.io.ReadOnlyAccessInputStream;
import com.github.junrar.rarfile.FileHeader;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class ComprDataIO {
private final Archive archive;
private long unpPackedSize;
private boolean testMode;
private boolean skipUnpCRC;
private InputStream inputStream;
private OutputStream outputStream;
private FileHeader subHead;
// cryptData Crypt;
// cryptData Decrypt;
private boolean packVolume;
private boolean unpVolume;
private boolean nextVolumeMissing;
private long totalPackRead;
private long unpArcSize;
private long curPackRead, curPackWrite, curUnpRead, curUnpWrite;
private long processedArcSize, totalArcSize;
private long packFileCRC, unpFileCRC, packedCRC;
private int encryption;
private int decryption;
private int lastPercent;
private char currentCommand;
public ComprDataIO(Archive arc) {
this.archive = arc;
}
public void init(OutputStream outputStream) {
this.outputStream = outputStream;
unpPackedSize = 0;
testMode = false;
skipUnpCRC = false;
packVolume = false;
unpVolume = false;
nextVolumeMissing = false;
// command = null;
encryption = 0;
decryption = 0;
totalPackRead = 0;
curPackRead = curPackWrite = curUnpRead = curUnpWrite = 0;
packFileCRC = unpFileCRC = packedCRC = 0xffffffff;
lastPercent = -1;
subHead = null;
currentCommand = 0;
processedArcSize = totalArcSize = 0;
}
public void init(FileHeader hd) throws IOException {
long startPos = hd.getPositionInFile() + hd.getHeaderSize();
unpPackedSize = hd.getFullPackSize();
inputStream = new ReadOnlyAccessInputStream(archive.getRof(), startPos,
startPos + unpPackedSize);
subHead = hd;
curUnpRead = 0;
curPackWrite = 0;
packedCRC = 0xFFffFFff;
}
public int unpRead(byte[] addr, int offset, int count) throws IOException,
RarException {
int retCode = 0, totalRead = 0;
while (count > 0) {
int readSize = (count > unpPackedSize) ? (int) unpPackedSize
: count;
retCode = inputStream.read(addr, offset, readSize);
if (retCode < 0) {
throw new EOFException();
}
if (subHead.isSplitAfter()) {
packedCRC = RarCRC.checkCrc((int) packedCRC, addr, offset,
retCode);
}
curUnpRead += retCode;
totalRead += retCode;
offset += retCode;
count -= retCode;
unpPackedSize -= retCode;
archive.bytesReadRead(retCode);
if (unpPackedSize == 0 && subHead.isSplitAfter()) {
Volume nextVolume = archive.getVolumeManager().nextArchive(
archive, archive.getVolume());
if (nextVolume == null) {
nextVolumeMissing = true;
return -1;
}
FileHeader hd = this.getSubHeader();
if (hd.getUnpVersion() >= 20 && hd.getFileCRC() != 0xffffffff
&& this.getPackedCRC() != ~hd.getFileCRC()) {
throw new RarException(RarExceptionType.crcError);
}
UnrarCallback callback = archive.getUnrarCallback();
if ((callback != null)
&& !callback.isNextVolumeReady(nextVolume)) {
return -1;
}
archive.setVolume(nextVolume);
hd = archive.nextFileHeader();
if (hd == null) {
return -1;
}
this.init(hd);
} else {
break;
}
}
if (retCode != -1) {
retCode = totalRead;
}
return retCode;
}
public void unpWrite(byte[] addr, int offset, int count) throws IOException {
if (!testMode) {
// DestFile->Write(Addr,Count);
outputStream.write(addr, offset, count);
}
curUnpWrite += count;
if (!skipUnpCRC) {
if (archive.isOldFormat()) {
unpFileCRC = RarCRC
.checkOldCrc((short) unpFileCRC, addr, count);
} else {
unpFileCRC = RarCRC.checkCrc((int) unpFileCRC, addr, offset,
count);
}
}
// if (!skipArcCRC) {
// archive.updateDataCRC(Addr, offset, ReadSize);
// }
}
public void setPackedSizeToRead(long size) {
unpPackedSize = size;
}
public void setTestMode(boolean mode) {
testMode = mode;
}
public void setSkipUnpCRC(boolean skip) {
skipUnpCRC = skip;
}
public void setSubHeader(FileHeader hd) {
subHead = hd;
}
public long getCurPackRead() {
return curPackRead;
}
public void setCurPackRead(long curPackRead) {
this.curPackRead = curPackRead;
}
public long getCurPackWrite() {
return curPackWrite;
}
public void setCurPackWrite(long curPackWrite) {
this.curPackWrite = curPackWrite;
}
public long getCurUnpRead() {
return curUnpRead;
}
public void setCurUnpRead(long curUnpRead) {
this.curUnpRead = curUnpRead;
}
public long getCurUnpWrite() {
return curUnpWrite;
}
public void setCurUnpWrite(long curUnpWrite) {
this.curUnpWrite = curUnpWrite;
}
public int getDecryption() {
return decryption;
}
public void setDecryption(int decryption) {
this.decryption = decryption;
}
public int getEncryption() {
return encryption;
}
public void setEncryption(int encryption) {
this.encryption = encryption;
}
public boolean isNextVolumeMissing() {
return nextVolumeMissing;
}
public void setNextVolumeMissing(boolean nextVolumeMissing) {
this.nextVolumeMissing = nextVolumeMissing;
}
public long getPackedCRC() {
return packedCRC;
}
public void setPackedCRC(long packedCRC) {
this.packedCRC = packedCRC;
}
public long getPackFileCRC() {
return packFileCRC;
}
public void setPackFileCRC(long packFileCRC) {
this.packFileCRC = packFileCRC;
}
public boolean isPackVolume() {
return packVolume;
}
public void setPackVolume(boolean packVolume) {
this.packVolume = packVolume;
}
public long getProcessedArcSize() {
return processedArcSize;
}
public void setProcessedArcSize(long processedArcSize) {
this.processedArcSize = processedArcSize;
}
public long getTotalArcSize() {
return totalArcSize;
}
public void setTotalArcSize(long totalArcSize) {
this.totalArcSize = totalArcSize;
}
public long getTotalPackRead() {
return totalPackRead;
}
public void setTotalPackRead(long totalPackRead) {
this.totalPackRead = totalPackRead;
}
public long getUnpArcSize() {
return unpArcSize;
}
public void setUnpArcSize(long unpArcSize) {
this.unpArcSize = unpArcSize;
}
public long getUnpFileCRC() {
return unpFileCRC;
}
public void setUnpFileCRC(long unpFileCRC) {
this.unpFileCRC = unpFileCRC;
}
public boolean isUnpVolume() {
return unpVolume;
}
public void setUnpVolume(boolean unpVolume) {
this.unpVolume = unpVolume;
}
public FileHeader getSubHeader() {
return subHead;
}
// public void setEncryption(int method, char[] Password, byte[] Salt,
// boolean encrypt, boolean handsOffHash)
// {
//
// }
//
// public void setAV15Encryption()
// {
//
// }
//
// public void setCmt13Encryption()
// {
//
// }
}