Repository: edmund-wagner/junrar
Branch: master
Commit: d1079dfb557a
Files: 98
Total size: 344.3 KB
Directory structure:
gitextract_8hmv49fy/
├── .gitignore
├── license.txt
├── testutil/
│ ├── .gitignore
│ ├── pom.xml
│ └── src/
│ └── main/
│ ├── java/
│ │ └── com/
│ │ └── github/
│ │ └── junrar/
│ │ └── testutil/
│ │ ├── ExtractArchive.java
│ │ └── JUnRarTestUtil.java
│ └── resources/
│ └── META-INF/
│ └── MANIFEST.MF
└── unrar/
├── .gitignore
├── generate-testdata.sh
├── pom.xml
├── readme.md
└── src/
└── main/
└── java/
└── com/
└── github/
└── junrar/
├── Archive.java
├── MVTest.java
├── UnrarCallback.java
├── Volume.java
├── VolumeManager.java
├── crc/
│ └── RarCRC.java
├── crypt/
│ └── Rijndael.java
├── exception/
│ └── RarException.java
├── impl/
│ ├── FileVolume.java
│ └── FileVolumeManager.java
├── io/
│ ├── IReadOnlyAccess.java
│ ├── InputStreamReadOnlyAccessFile.java
│ ├── RandomAccessStream.java
│ ├── Raw.java
│ ├── ReadOnlyAccessByteArray.java
│ ├── ReadOnlyAccessFile.java
│ └── ReadOnlyAccessInputStream.java
├── rarfile/
│ ├── AVHeader.java
│ ├── BaseBlock.java
│ ├── BlockHeader.java
│ ├── CommentHeader.java
│ ├── EAHeader.java
│ ├── EndArcHeader.java
│ ├── FileHeader.java
│ ├── FileNameDecoder.java
│ ├── HostSystem.java
│ ├── MacInfoHeader.java
│ ├── MainHeader.java
│ ├── MarkHeader.java
│ ├── NewSubHeaderType.java
│ ├── ProtectHeader.java
│ ├── SignHeader.java
│ ├── SubBlockHeader.java
│ ├── SubBlockHeaderType.java
│ ├── UnixOwnersHeader.java
│ └── UnrarHeadertype.java
├── unpack/
│ ├── ComprDataIO.java
│ ├── Unpack.java
│ ├── Unpack15.java
│ ├── Unpack20.java
│ ├── UnpackFilter.java
│ ├── decode/
│ │ ├── AudioVariables.java
│ │ ├── BitDecode.java
│ │ ├── CodeType.java
│ │ ├── Compress.java
│ │ ├── Decode.java
│ │ ├── DistDecode.java
│ │ ├── FilterType.java
│ │ ├── LitDecode.java
│ │ ├── LowDistDecode.java
│ │ ├── MultDecode.java
│ │ └── RepDecode.java
│ ├── ppm/
│ │ ├── AnalyzeHeapDump.java
│ │ ├── BlockTypes.java
│ │ ├── FreqData.java
│ │ ├── ModelPPM.java
│ │ ├── PPMContext.java
│ │ ├── Pointer.java
│ │ ├── RangeCoder.java
│ │ ├── RarMemBlock.java
│ │ ├── RarNode.java
│ │ ├── SEE2Context.java
│ │ ├── State.java
│ │ ├── StateRef.java
│ │ └── SubAllocator.java
│ └── vm/
│ ├── BitInput.java
│ ├── RarVM.java
│ ├── VMCmdFlags.java
│ ├── VMCommands.java
│ ├── VMFlags.java
│ ├── VMOpType.java
│ ├── VMPreparedCommand.java
│ ├── VMPreparedOperand.java
│ ├── VMPreparedProgram.java
│ ├── VMStandardFilterSignature.java
│ └── VMStandardFilters.java
├── unsigned/
│ ├── UnsignedByte.java
│ ├── UnsignedInteger.java
│ ├── UnsignedLong.java
│ └── UnsignedShort.java
├── util/
│ └── VolumeHelper.java
└── vfs2/
└── provider/
└── rar/
├── RARFileObject.java
├── RARFileProvider.java
├── RARFileSystem.java
├── RandomAccessContentAccess.java
├── VFSVolume.java
└── VFSVolumeManager.java
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.classpath
.project
.settings/
target/
================================================
FILE: license.txt
================================================
****** ***** ****** UnRAR - free utility for RAR archives
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
****** ******* ****** License for use and distribution of
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
** ** ** ** ** ** FREE portable version
~~~~~~~~~~~~~~~~~~~~~
The source code of UnRAR utility is freeware. This means:
1. All copyrights to RAR and the utility UnRAR are exclusively
owned by the author - Alexander Roshal.
2. The UnRAR sources may be used in any software to handle RAR
archives without limitations free of charge, but cannot be used
to re-create the RAR compression algorithm, which is proprietary.
Distribution of modified UnRAR sources in separate form or as a
part of other software is permitted, provided that it is clearly
stated in the documentation and source comments that the code may
not be used to develop a RAR (WinRAR) compatible archiver.
3. The UnRAR utility may be freely distributed. It is allowed
to distribute UnRAR inside of other software packages.
4. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
OR MISUSING THIS SOFTWARE.
5. Installing and using the UnRAR utility signifies acceptance of
these terms and conditions of the license.
6. If you don't agree with terms of the license you must remove
UnRAR files from your storage devices and cease to use the
utility.
Thank you for your interest in RAR and UnRAR.
Alexander L. Roshal
================================================
FILE: testutil/.gitignore
================================================
.classpath
.project
bin/
.checkstyle
================================================
FILE: testutil/pom.xml
================================================
4.0.0
com.github.junrar
junrar-testutil
jar
0.1
java-unrar-testutil
http://maven.apache.org
edmund_wagner
Edmund Wagner
edmund_wagner@users.sourceforge.net
org.apache.maven.plugins
maven-jar-plugin
2.2
de.innosystec.unrar.testutil.JUnRarTestUtil
de.innosystec.unrar.testutil
true
development
${pom.url}
src/main/resources/META-INF/MANIFEST.MF
junit
junit
3.8.1
test
com.github.junrar
junrar
0.6-SNAPSHOT
================================================
FILE: testutil/src/main/java/com/github/junrar/testutil/ExtractArchive.java
================================================
package com.github.junrar.testutil;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.junrar.Archive;
import com.github.junrar.exception.RarException;
import com.github.junrar.rarfile.FileHeader;
/**
* extract an archive to the given location
*
* @author edmund wagner
*
*/
public class ExtractArchive {
private static Log logger = LogFactory.getLog(ExtractArchive.class
.getName());
public static void extractArchive(String archive, String destination) {
if (archive == null || destination == null) {
throw new RuntimeException("archive and destination must me set");
}
File arch = new File(archive);
if (!arch.exists()) {
throw new RuntimeException("the archive does not exit: " + archive);
}
File dest = new File(destination);
if (!dest.exists() || !dest.isDirectory()) {
throw new RuntimeException(
"the destination must exist and point to a directory: "
+ destination);
}
extractArchive(arch, dest);
}
public static void main(String[] args) {
if (args.length == 2) {
extractArchive(args[0], args[1]);
} else {
System.out
.println("usage: java -jar extractArchive.jar ");
}
}
public static void extractArchive(File archive, File destination) {
Archive arch = null;
try {
arch = new Archive(archive);
} catch (RarException e) {
logger.error(e);
} catch (IOException e1) {
logger.error(e1);
}
if (arch != null) {
if (arch.isEncrypted()) {
logger.warn("archive is encrypted cannot extreact");
return;
}
FileHeader fh = null;
while (true) {
fh = arch.nextFileHeader();
if (fh == null) {
break;
}
if (fh.isEncrypted()) {
logger.warn("file is encrypted cannot extract: "
+ fh.getFileNameString());
continue;
}
logger.info("extracting: " + fh.getFileNameString());
try {
if (fh.isDirectory()) {
createDirectory(fh, destination);
} else {
File f = createFile(fh, destination);
OutputStream stream = new FileOutputStream(f);
arch.extractFile(fh, stream);
stream.close();
}
} catch (IOException e) {
logger.error("error extracting the file", e);
} catch (RarException e) {
logger.error("error extraction the file", e);
}
}
}
}
private static File createFile(FileHeader fh, File destination) {
File f = null;
String name = null;
if (fh.isFileHeader() && fh.isUnicode()) {
name = fh.getFileNameW();
} else {
name = fh.getFileNameString();
}
f = new File(destination, name);
if (!f.exists()) {
try {
f = makeFile(destination, name);
} catch (IOException e) {
logger.error("error creating the new file: " + f.getName(), e);
}
}
return f;
}
private static File makeFile(File destination, String name)
throws IOException {
String[] dirs = name.split("\\\\");
if (dirs == null) {
return null;
}
String path = "";
int size = dirs.length;
if (size == 1) {
return new File(destination, name);
} else if (size > 1) {
for (int i = 0; i < dirs.length - 1; i++) {
path = path + File.separator + dirs[i];
new File(destination, path).mkdir();
}
path = path + File.separator + dirs[dirs.length - 1];
File f = new File(destination, path);
f.createNewFile();
return f;
} else {
return null;
}
}
private static void createDirectory(FileHeader fh, File destination) {
File f = null;
if (fh.isDirectory() && fh.isUnicode()) {
f = new File(destination, fh.getFileNameW());
if (!f.exists()) {
makeDirectory(destination, fh.getFileNameW());
}
} else if (fh.isDirectory() && !fh.isUnicode()) {
f = new File(destination, fh.getFileNameString());
if (!f.exists()) {
makeDirectory(destination, fh.getFileNameString());
}
}
}
private static void makeDirectory(File destination, String fileName) {
String[] dirs = fileName.split("\\\\");
if (dirs == null) {
return;
}
String path = "";
for (String dir : dirs) {
path = path + File.separator + dir;
new File(destination, path).mkdir();
}
}
}
================================================
FILE: testutil/src/main/java/com/github/junrar/testutil/JUnRarTestUtil.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: EW
* Creation date: 26.09.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.testutil;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.junrar.Archive;
import com.github.junrar.exception.RarException;
import com.github.junrar.exception.RarException.RarExceptionType;
import com.github.junrar.io.ReadOnlyAccessFile;
import com.github.junrar.rarfile.FileHeader;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class JUnRarTestUtil
{
private static Log logger = LogFactory.getLog(JUnRarTestUtil.class.getName());
/**
* @param args
*/
private static List successfulFiles = new ArrayList();
private static List errorFiles = new ArrayList();
private static List unsupportedFiles = new ArrayList();
public static void main(String[] args)
{
if(args.length!=1){
System.out.println("JUnRar TestUtil\n usage: java -jar unrar-test.jar ");
return;
}else{
File file = new File(args[0]);
if(file.exists()){
if(file.isDirectory()){
recurseDirectory(file);
}else{
testFile(file);
}
}
}
printSummary();
}
private static void printSummary()
{
System.out.println("\n\n\nSuccessfully tested archives:\n");
for(String sf:successfulFiles){
System.out.println(sf);
}
System.out.println("");
System.out.println("Unsupported archives:\n");
for(String uf: unsupportedFiles){
System.out.println(uf);
}
System.out.println("");
System.out.println("Failed archives:");
for(String ff: errorFiles){
System.out.println(ff);
}
System.out.println("");
System.out.println("\n\n\nSummary\n");
System.out.println("tested:\t\t"+(successfulFiles.size()+unsupportedFiles.size()+errorFiles.size()));
System.out.println("successful:\t"+successfulFiles.size());
System.out.println("unsupported:\t"+unsupportedFiles.size());
System.out.println("failed:\t\t"+errorFiles.size());
}
private static void testFile(File file)
{
if(file==null || !file.exists()){
logger.error("error file " +file + " does not exist");
return;
}
logger.info(">>>>>> testing archive: "+file);
String s = file.toString();
s = s.substring(s.length()-3);
if(s.equalsIgnoreCase("rar")){
System.out.println(file.toString());
ReadOnlyAccessFile readFile = null;
try {
// readFile = new ReadOnlyAccessFile(file);
Archive arc = null;
try {
arc = new Archive(file);
} catch (RarException e) {
logger.error("archive consturctor error",e);
errorFiles.add(file.toString());
return;
}
if(arc != null){
if(arc.isEncrypted()){
logger.warn("archive is encrypted cannot extreact");
unsupportedFiles.add(file.toString());
return;
}
List files = arc.getFileHeaders();
for(FileHeader fh : files)
{
if(fh.isEncrypted()){
logger.warn("file is encrypted cannot extract: "+fh.getFileNameString());
unsupportedFiles.add(file.toString());
return;
}
logger.info("extracting file: "+fh.getFileNameString());
if(fh.isFileHeader() && fh.isUnicode()){
logger.info("unicode name: "+fh.getFileNameW());
}
logger.info("start: "+new Date());
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
arc.extractFile(fh, os);
} catch (RarException e) {
if(e.getType().equals(RarExceptionType.notImplementedYet)){
logger.error("error extracting unsupported file: "+fh.getFileNameString(),e);
unsupportedFiles.add(file.toString());
return;
}
logger.error("error extracting file: "+fh.getFileNameString(),e);
errorFiles.add(file.toString());
return;
}finally{
os.close();
}
logger.info("end: "+new Date());
}
}
logger.info("successfully tested archive: "+file);
successfulFiles.add(file.toString());
} catch (Exception e) {
logger.error("file: "+file+ " extraction error - does the file exist?"+e );
errorFiles.add(file.toString());
} finally{
if(readFile!=null){
try {
readFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
private static void recurseDirectory(File file)
{
if(file==null||!file.exists()){
return;
}
if(file.isDirectory()){
File[] files = file.listFiles();
if(files == null){
return;
}
for(File f: files){
recurseDirectory(f);
f = null;
}
}else{
testFile(file);
file=null;
}
}
}
================================================
FILE: testutil/src/main/resources/META-INF/MANIFEST.MF
================================================
================================================
FILE: unrar/.gitignore
================================================
.classpath
.project
================================================
FILE: unrar/generate-testdata.sh
================================================
mode=$1
adstepping=$2
t1stepping=$3
t2stepping=$4
indir=$5
outdir=$6
par1=1
par2=1
path=$PWD
function start {
case "$1" in
a|d)
.
while [ $par1 -le 31 ]
do
rar a -ep1 -mc$par1$1+ $path/$outdir/$i/$i-mc$par1$1+.rar $path/$indir/$i
let par1+=adstepping
done
par1=1
;;
t)
let par1=2
while [ $par1 -le 63 ]
do
while [ $par2 -le 128 ]
do
rar a -ep1 -mc$par1:$par2$1+ $path/$outdir/$i/$i-mc$par1.$par2$1+.rar $path/$indir/$i
let par2+=$t2stepping
done
let par1+=$t1stepping
let par2=1
done
par1=1
;;
c|e|i)
rar a -ep1 -mc$1+ $path/$outdir/$i/$i-mc$1+.rar $path/$indir/$i
par1=1
;;
n)
rar a -ep1 -mca- -mcd- -mct- -mcc- -mce- -mci- $path/$outdir/$i/$i-n.rar $path/$indir/$i
;;
esac
}
if [ "$mode" != "" ] && [ "$adstepping" != "" ] &&[ "$t1stepping" != "" ] && [ "$t2stepping" != "" ] && [ "$indir" != "" ] && [ "$outdir" != "" ];
then
# create output dir
mkdir -m 0777 $outdir
cd $indir
for i in $(ls *)
do
mkdir -m 0777 $path/$outdir/$i
if [ "$1" == "all" ];then
start a
start d
start c
start e
start i
start t
start n
else
start "$mode"
fi
done
else
echo "usage: ./generate-testdata.sh [ a | d | c | e | i | t | n | all ] [ adstepping ] [ t1stepping] [ t2stepping] [ indir ] [ outdir ]"
echo .......................................
exit 0
fi
================================================
FILE: unrar/pom.xml
================================================
4.0.0
com.github.beothorn
junrar
jar
0.7-SNAPSHOT
Java UnRar
rar decompression library in plain java
https://github.com/edmund-wagner/junrar
UTF-8
1.6
1.6
UnRar License
https://raw.github.com/edmund-wagner/junrar/master/license.txt
repo
scm:git:git@github.com:edmund-wagner/junrar.git
scm:git:git@github.com:edmund-wagner/junrar.git
git@github.com:edmund-wagner/junrar.git
edmund_wagner
Edmund Wagner
junit
junit
3.8.1
jar
test
false
commons-logging
commons-logging-api
1.1
jar
false
org.apache.commons
commons-vfs2
2.0
true
org.apache.maven.plugins
maven-release-plugin
2.2.1
sign
org.apache.maven.plugins
maven-compiler-plugin
2.3.2
${maven.compiler.source}
${maven.compiler.source}
${project.build.sourceEncoding}
org.apache.maven.plugins
maven-gpg-plugin
sign-artifacts
verify
sign
org.sonatype.oss
oss-parent
7
================================================
FILE: unrar/readme.md
================================================
unrar
=====
Adds support to read a rar from a given InputStream.
Additional dependencies
-----------------------
* ij: http://rsbweb.nih.gov/ij/
================================================
FILE: unrar/src/main/java/com/github/junrar/Archive.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 22.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;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.github.junrar.exception.RarException;
import com.github.junrar.exception.RarException.RarExceptionType;
import com.github.junrar.impl.FileVolumeManager;
import com.github.junrar.io.IReadOnlyAccess;
import com.github.junrar.rarfile.AVHeader;
import com.github.junrar.rarfile.BaseBlock;
import com.github.junrar.rarfile.BlockHeader;
import com.github.junrar.rarfile.CommentHeader;
import com.github.junrar.rarfile.EAHeader;
import com.github.junrar.rarfile.EndArcHeader;
import com.github.junrar.rarfile.FileHeader;
import com.github.junrar.rarfile.MacInfoHeader;
import com.github.junrar.rarfile.MainHeader;
import com.github.junrar.rarfile.MarkHeader;
import com.github.junrar.rarfile.ProtectHeader;
import com.github.junrar.rarfile.SignHeader;
import com.github.junrar.rarfile.SubBlockHeader;
import com.github.junrar.rarfile.UnixOwnersHeader;
import com.github.junrar.rarfile.UnrarHeadertype;
import com.github.junrar.unpack.ComprDataIO;
import com.github.junrar.unpack.Unpack;
/**
* The Main Rar Class; represents a rar Archive
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class Archive implements Closeable {
private static Logger logger = Logger.getLogger(Archive.class.getName());
private IReadOnlyAccess rof;
private final UnrarCallback unrarCallback;
private final ComprDataIO dataIO;
private final List headers = new ArrayList();
private MarkHeader markHead = null;
private MainHeader newMhd = null;
private Unpack unpack;
private int currentHeaderIndex;
/** Size of packed data in current file. */
private long totalPackedSize = 0L;
/** Number of bytes of compressed data read from current file. */
private long totalPackedRead = 0L;
private VolumeManager volumeManager;
private Volume volume;
public Archive(VolumeManager volumeManager) throws RarException,
IOException {
this(volumeManager, null);
}
/**
* create a new archive object using the given {@link VolumeManager}
*
* @param volumeManager
* the the {@link VolumeManager} that will provide volume stream
* data
* @throws RarException
*/
public Archive(VolumeManager volumeManager, UnrarCallback unrarCallback)
throws RarException, IOException {
this.volumeManager = volumeManager;
this.unrarCallback = unrarCallback;
setVolume(this.volumeManager.nextArchive(this, null));
dataIO = new ComprDataIO(this);
}
public Archive(File firstVolume) throws RarException, IOException {
this(new FileVolumeManager(firstVolume), null);
}
public Archive(File firstVolume, UnrarCallback unrarCallback)
throws RarException, IOException {
this(new FileVolumeManager(firstVolume), unrarCallback);
}
// public File getFile() {
// return file;
// }
//
// void setFile(File file) throws IOException {
// this.file = file;
// setFile(new ReadOnlyAccessFile(file), file.length());
// }
private void setFile(IReadOnlyAccess file, long length) throws IOException {
totalPackedSize = 0L;
totalPackedRead = 0L;
close();
rof = file;
try {
readHeaders(length);
} catch (Exception e) {
logger.log(Level.WARNING,
"exception in archive constructor maybe file is encrypted "
+ "or currupt", e);
// ignore exceptions to allow exraction of working files in
// corrupt archive
}
// Calculate size of packed data
for (BaseBlock block : headers) {
if (block.getHeaderType() == UnrarHeadertype.FileHeader) {
totalPackedSize += ((FileHeader) block).getFullPackSize();
}
}
if (unrarCallback != null) {
unrarCallback.volumeProgressChanged(totalPackedRead,
totalPackedSize);
}
}
public void bytesReadRead(int count) {
if (count > 0) {
totalPackedRead += count;
if (unrarCallback != null) {
unrarCallback.volumeProgressChanged(totalPackedRead,
totalPackedSize);
}
}
}
public IReadOnlyAccess getRof() {
return rof;
}
/**
* @return returns all file headers of the archive
*/
public List getFileHeaders() {
List list = new ArrayList();
for (BaseBlock block : headers) {
if (block.getHeaderType().equals(UnrarHeadertype.FileHeader)) {
list.add((FileHeader) block);
}
}
return list;
}
public FileHeader nextFileHeader() {
int n = headers.size();
while (currentHeaderIndex < n) {
BaseBlock block = headers.get(currentHeaderIndex++);
if (block.getHeaderType() == UnrarHeadertype.FileHeader) {
return (FileHeader) block;
}
}
return null;
}
public UnrarCallback getUnrarCallback() {
return unrarCallback;
}
/**
*
* @return whether the archive is encrypted
*/
public boolean isEncrypted() {
if (newMhd != null) {
return newMhd.isEncrypted();
} else {
throw new NullPointerException("mainheader is null");
}
}
/**
* Read the headers of the archive
*
* @param fileLength
* Length of file.
* @throws RarException
*/
private void readHeaders(long fileLength) throws IOException, RarException {
markHead = null;
newMhd = null;
headers.clear();
currentHeaderIndex = 0;
int toRead = 0;
while (true) {
int size = 0;
long newpos = 0;
byte[] baseBlockBuffer = new byte[BaseBlock.BaseBlockSize];
long position = rof.getPosition();
// Weird, but is trying to read beyond the end of the file
if (position >= fileLength) {
break;
}
// logger.info("\n--------reading header--------");
size = rof.readFully(baseBlockBuffer, BaseBlock.BaseBlockSize);
if (size == 0) {
break;
}
BaseBlock block = new BaseBlock(baseBlockBuffer);
block.setPositionInFile(position);
switch (block.getHeaderType()) {
case MarkHeader:
markHead = new MarkHeader(block);
if (!markHead.isSignature()) {
throw new RarException(
RarException.RarExceptionType.badRarArchive);
}
headers.add(markHead);
// markHead.print();
break;
case MainHeader:
toRead = block.hasEncryptVersion() ? MainHeader.mainHeaderSizeWithEnc
: MainHeader.mainHeaderSize;
byte[] mainbuff = new byte[toRead];
rof.readFully(mainbuff, toRead);
MainHeader mainhead = new MainHeader(block, mainbuff);
headers.add(mainhead);
this.newMhd = mainhead;
if (newMhd.isEncrypted()) {
throw new RarException(
RarExceptionType.rarEncryptedException);
}
// mainhead.print();
break;
case SignHeader:
toRead = SignHeader.signHeaderSize;
byte[] signBuff = new byte[toRead];
rof.readFully(signBuff, toRead);
SignHeader signHead = new SignHeader(block, signBuff);
headers.add(signHead);
// logger.info("HeaderType: SignHeader");
break;
case AvHeader:
toRead = AVHeader.avHeaderSize;
byte[] avBuff = new byte[toRead];
rof.readFully(avBuff, toRead);
AVHeader avHead = new AVHeader(block, avBuff);
headers.add(avHead);
// logger.info("headertype: AVHeader");
break;
case CommHeader:
toRead = CommentHeader.commentHeaderSize;
byte[] commBuff = new byte[toRead];
rof.readFully(commBuff, toRead);
CommentHeader commHead = new CommentHeader(block, commBuff);
headers.add(commHead);
// logger.info("method: "+commHead.getUnpMethod()+"; 0x"+
// Integer.toHexString(commHead.getUnpMethod()));
newpos = commHead.getPositionInFile()
+ commHead.getHeaderSize();
rof.setPosition(newpos);
break;
case EndArcHeader:
toRead = 0;
if (block.hasArchiveDataCRC()) {
toRead += EndArcHeader.endArcArchiveDataCrcSize;
}
if (block.hasVolumeNumber()) {
toRead += EndArcHeader.endArcVolumeNumberSize;
}
EndArcHeader endArcHead;
if (toRead > 0) {
byte[] endArchBuff = new byte[toRead];
rof.readFully(endArchBuff, toRead);
endArcHead = new EndArcHeader(block, endArchBuff);
// logger.info("HeaderType: endarch\ndatacrc:"+
// endArcHead.getArchiveDataCRC());
} else {
// logger.info("HeaderType: endarch - no Data");
endArcHead = new EndArcHeader(block, null);
}
headers.add(endArcHead);
// logger.info("\n--------end header--------");
return;
default:
byte[] blockHeaderBuffer = new byte[BlockHeader.blockHeaderSize];
rof.readFully(blockHeaderBuffer, BlockHeader.blockHeaderSize);
BlockHeader blockHead = new BlockHeader(block,
blockHeaderBuffer);
switch (blockHead.getHeaderType()) {
case NewSubHeader:
case FileHeader:
toRead = blockHead.getHeaderSize()
- BlockHeader.BaseBlockSize
- BlockHeader.blockHeaderSize;
byte[] fileHeaderBuffer = new byte[toRead];
rof.readFully(fileHeaderBuffer, toRead);
FileHeader fh = new FileHeader(blockHead, fileHeaderBuffer);
headers.add(fh);
newpos = fh.getPositionInFile() + fh.getHeaderSize()
+ fh.getFullPackSize();
rof.setPosition(newpos);
break;
case ProtectHeader:
toRead = blockHead.getHeaderSize()
- BlockHeader.BaseBlockSize
- BlockHeader.blockHeaderSize;
byte[] protectHeaderBuffer = new byte[toRead];
rof.readFully(protectHeaderBuffer, toRead);
ProtectHeader ph = new ProtectHeader(blockHead,
protectHeaderBuffer);
newpos = ph.getPositionInFile() + ph.getHeaderSize()
+ ph.getDataSize();
rof.setPosition(newpos);
break;
case SubHeader: {
byte[] subHeadbuffer = new byte[SubBlockHeader.SubBlockHeaderSize];
rof.readFully(subHeadbuffer,
SubBlockHeader.SubBlockHeaderSize);
SubBlockHeader subHead = new SubBlockHeader(blockHead,
subHeadbuffer);
subHead.print();
switch (subHead.getSubType()) {
case MAC_HEAD: {
byte[] macHeaderbuffer = new byte[MacInfoHeader.MacInfoHeaderSize];
rof.readFully(macHeaderbuffer,
MacInfoHeader.MacInfoHeaderSize);
MacInfoHeader macHeader = new MacInfoHeader(subHead,
macHeaderbuffer);
macHeader.print();
headers.add(macHeader);
break;
}
// TODO implement other subheaders
case BEEA_HEAD:
break;
case EA_HEAD: {
byte[] eaHeaderBuffer = new byte[EAHeader.EAHeaderSize];
rof.readFully(eaHeaderBuffer, EAHeader.EAHeaderSize);
EAHeader eaHeader = new EAHeader(subHead,
eaHeaderBuffer);
eaHeader.print();
headers.add(eaHeader);
break;
}
case NTACL_HEAD:
break;
case STREAM_HEAD:
break;
case UO_HEAD:
toRead = subHead.getHeaderSize();
toRead -= BaseBlock.BaseBlockSize;
toRead -= BlockHeader.blockHeaderSize;
toRead -= SubBlockHeader.SubBlockHeaderSize;
byte[] uoHeaderBuffer = new byte[toRead];
rof.readFully(uoHeaderBuffer, toRead);
UnixOwnersHeader uoHeader = new UnixOwnersHeader(
subHead, uoHeaderBuffer);
uoHeader.print();
headers.add(uoHeader);
break;
default:
break;
}
break;
}
default:
logger.warning("Unknown Header");
throw new RarException(RarExceptionType.notRarArchive);
}
}
// logger.info("\n--------end header--------");
}
}
/**
* Extract the file specified by the given header and write it to the
* supplied output stream
*
* @param header
* the header to be extracted
* @param os
* the outputstream
* @throws RarException
*/
public void extractFile(FileHeader hd, OutputStream os) throws RarException {
if (!headers.contains(hd)) {
throw new RarException(RarExceptionType.headerNotInArchive);
}
try {
doExtractFile(hd, os);
} catch (Exception e) {
if (e instanceof RarException) {
throw (RarException) e;
} else {
throw new RarException(e);
}
}
}
/**
* Returns an {@link InputStream} that will allow to read the file and
* stream it. Please note that this method will create a new Thread and an a
* pair of Pipe streams.
*
* @param header
* the header to be extracted
* @throws RarException
* @throws IOException
* if any IO error occur
*/
public InputStream getInputStream(final FileHeader hd) throws RarException,
IOException {
final PipedInputStream in = new PipedInputStream(32 * 1024);
final PipedOutputStream out = new PipedOutputStream(in);
// creates a new thread that will write data to the pipe. Data will be
// available in another InputStream, connected to the OutputStream.
new Thread(new Runnable() {
public void run() {
try {
extractFile(hd, out);
} catch (RarException e) {
} finally {
try {
out.close();
} catch (IOException e) {
}
}
}
}).start();
return in;
}
private void doExtractFile(FileHeader hd, OutputStream os)
throws RarException, IOException {
dataIO.init(os);
dataIO.init(hd);
dataIO.setUnpFileCRC(this.isOldFormat() ? 0 : 0xffFFffFF);
if (unpack == null) {
unpack = new Unpack(dataIO);
}
if (!hd.isSolid()) {
unpack.init(null);
}
unpack.setDestSize(hd.getFullUnpackSize());
try {
unpack.doUnpack(hd.getUnpVersion(), hd.isSolid());
// Verify file CRC
hd = dataIO.getSubHeader();
long actualCRC = hd.isSplitAfter() ? ~dataIO.getPackedCRC()
: ~dataIO.getUnpFileCRC();
int expectedCRC = hd.getFileCRC();
if (actualCRC != expectedCRC) {
throw new RarException(RarExceptionType.crcError);
}
// if (!hd.isSplitAfter()) {
// // Verify file CRC
// if(~dataIO.getUnpFileCRC() != hd.getFileCRC()){
// throw new RarException(RarExceptionType.crcError);
// }
// }
} catch (Exception e) {
unpack.cleanUp();
if (e instanceof RarException) {
// throw new RarException((RarException)e);
throw (RarException) e;
} else {
throw new RarException(e);
}
}
}
/**
* @return returns the main header of this archive
*/
public MainHeader getMainHeader() {
return newMhd;
}
/**
* @return whether the archive is old format
*/
public boolean isOldFormat() {
return markHead.isOldFormat();
}
/** Close the underlying compressed file. */
public void close() throws IOException {
if (rof != null) {
rof.close();
rof = null;
}
if (unpack != null) {
unpack.cleanUp();
}
}
/**
* @return the volumeManager
*/
public VolumeManager getVolumeManager() {
return volumeManager;
}
/**
* @param volumeManager
* the volumeManager to set
*/
public void setVolumeManager(VolumeManager volumeManager) {
this.volumeManager = volumeManager;
}
/**
* @return the volume
*/
public Volume getVolume() {
return volume;
}
/**
* @param volume
* the volume to set
* @throws IOException
*/
public void setVolume(Volume volume) throws IOException {
this.volume = volume;
setFile(volume.getReadOnlyAccess(), volume.getLength());
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/MVTest.java
================================================
package com.github.junrar;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import com.github.junrar.exception.RarException;
import com.github.junrar.impl.FileVolumeManager;
import com.github.junrar.rarfile.FileHeader;
public class MVTest {
/**
* @param args
*/
public static void main(String[] args) {
String filename = "/home/rogiel/fs/home/ae721273-eade-45e7-8112-d14115ebae56/Village People - Y.M.C.A.mp3.part1.rar";
File f = new File(filename);
Archive a = null;
try {
a = new Archive(new FileVolumeManager(f));
} catch (RarException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (a != null) {
a.getMainHeader().print();
FileHeader fh = a.nextFileHeader();
while (fh != null) {
try {
File out = new File("/home/rogiel/fs/test/"
+ fh.getFileNameString().trim());
System.out.println(out.getAbsolutePath());
FileOutputStream os = new FileOutputStream(out);
a.extractFile(fh, os);
os.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RarException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
fh = a.nextFileHeader();
}
}
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/UnrarCallback.java
================================================
package com.github.junrar;
/**
*
* @author alban
*/
public interface UnrarCallback {
/**
* Return true if the next volume is ready to be processed,
* false otherwise.
*/
boolean isNextVolumeReady(Volume nextVolume);
/**
* This method is invoked each time the progress of the current
* volume changes.
*/
void volumeProgressChanged(long current, long total);
}
================================================
FILE: unrar/src/main/java/com/github/junrar/Volume.java
================================================
/*
* This file is part of seedbox .
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see .
*/
package com.github.junrar;
import java.io.IOException;
import com.github.junrar.io.IReadOnlyAccess;
/**
* @author Rogiel
*
*/
public interface Volume {
/**
* @return the access
* @throws IOException
*/
IReadOnlyAccess getReadOnlyAccess() throws IOException;
/**
* @return the data length
*/
long getLength();
/**
* @return the archive this volume belongs to
*/
Archive getArchive();
}
================================================
FILE: unrar/src/main/java/com/github/junrar/VolumeManager.java
================================================
/*
* This file is part of seedbox .
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see .
*/
package com.github.junrar;
import java.io.IOException;
/**
* @author Rogiel
*
*/
public interface VolumeManager {
public Volume nextArchive(Archive archive, Volume lastVolume)
throws IOException;
}
================================================
FILE: unrar/src/main/java/com/github/junrar/crc/RarCRC.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 29.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.crc;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class RarCRC {
private final static int crcTab[];
static {
crcTab = new int[256];
for (int i = 0; i < 256; i++) {
int c = i;
for (int j = 0; j < 8; j++){
if ((c & 1) !=0) {
c >>>= 1;
c ^= 0xEDB88320;
}
else{
c >>>= 1;
}
}
crcTab[i] = c;
}
}
private RarCRC() {
}
public static int checkCrc(int startCrc, byte[] data, int offset,
int count) {
int size = Math.min(data.length-offset,count);
// #if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) &&
// defined(ALLOW_NOT_ALIGNED_INT)
/*
for (int i = 0; (0 < size) && i < data.length - 8
&& ((data[i + 8] & 7) != 0); i++) {
startCrc = crcTab[(short) (startCrc ^ data[i]) & 0x00FF] ^ (startCrc >>> 8);
size--;
}
for (int i = 0; size >= 8; i += 8) {
startCrc ^= data[i + 0] << 24;
startCrc ^= data[i + 1] << 16;
startCrc ^= data[i + 2] << 8;
startCrc ^= data[i + 3];
startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8);
startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8);
startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8);
startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8);
startCrc ^= data[i + 4] << 24;
startCrc ^= data[i + 5] << 16;
startCrc ^= data[i + 6] << 8;
startCrc ^= data[i + 7];
startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8);
startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8);
startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8);
startCrc = crcTab[(short) startCrc & 0x00FF] ^ (startCrc >>> 8);
size -= 8;
}*/
for (int i = 0; i < size; i++)
{
/*
// (byte)(StartCRC^Data[I])
int pos = 0; // pos=0x00000000
pos |= startCrc; // pos=ffffffff
pos ^= data[i]; // data[0]=0x73=115dec --> pos=140
System.out.println(Integer.toHexString(pos));
// Only last 8 bit because CRCtab has length 256
pos = pos & 0x000000FF;
System.out.println("pos:"+pos);
//startCrc >>>= 8;
//StartCRC>>8
int temp =0;
temp|=startCrc;
temp >>>= 8;
System.out.println("temp:"+Integer.toHexString(temp));
startCrc = (crcTab[pos]^temp);
System.out.println("--"+Integer.toHexString(startCrc));*/
startCrc=(crcTab[((int)((int)startCrc ^
(int)data[offset+i]))&0xff]^(startCrc>>>8));
//System.out.println(Integer.toHexString(startCrc));
// Original code:
//StartCRC=CRCTab[(byte)(StartCRC^Data[I])]^(StartCRC>>8);
}
return (startCrc);
}
public static short checkOldCrc(short startCrc, byte[] data, int count) {
int n = Math.min(data.length, count);
for (int i = 0; i < n; i++) {
startCrc = (short) ((short) (startCrc + (short) (data[i]&0x00ff)) & -1);
startCrc = (short) (((startCrc << 1) | (startCrc >>> 15)) & -1);
}
return (startCrc);
}
// public static void main(String[] args)
// {
// RarCRC rc = new RarCRC();
// //byte[] data = { 0x72, 0x21, 0x1A, 0x07, 0x00};
//
// byte[] data = {0x73 ,0x00 ,0x00 ,0x0D ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00};
//
// int crc = 0x90CF;
//
//
// int result = rc.checkCrc(0xFFFFffff, data,0,data.length);
// System.out.println("3: "+Integer.toHexString(~result&0xffff));
//
// }
}
================================================
FILE: unrar/src/main/java/com/github/junrar/crypt/Rijndael.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 31.05.2007
*
* 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
* Source: $HeadURL$
* Last changed: $LastChangedDate$
*
* Here some html entities which can be used for escaping javadoc tags:
* "&": "&" or "&"
* "<": "<" or "<"
* ">": ">" or ">"
* "@": "@"
*/
package com.github.junrar.crypt;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class Rijndael {
}
================================================
FILE: unrar/src/main/java/com/github/junrar/exception/RarException.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 30.07.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.exception;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class RarException extends Exception
{
private static final long serialVersionUID = 1L;
private RarExceptionType type;
public RarException(Exception e){
super(RarExceptionType.unkownError.name(),e);
this.type = RarExceptionType.unkownError;
}
public RarException(RarException e)
{
super(e.getMessage(),e);
this.type = e.getType();
}
public RarException(RarExceptionType type){
super(type.name());
this.type = type;
}
public enum RarExceptionType{
notImplementedYet,
crcError,
notRarArchive,
badRarArchive,
unkownError,
headerNotInArchive,
wrongHeaderType,
ioError,
rarEncryptedException ;
}
public RarExceptionType getType()
{
return type;
}
public void setType(RarExceptionType type)
{
this.type = type;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/impl/FileVolume.java
================================================
/*
* This file is part of seedbox .
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see .
*/
package com.github.junrar.impl;
import java.io.File;
import java.io.IOException;
import com.github.junrar.Archive;
import com.github.junrar.Volume;
import com.github.junrar.io.IReadOnlyAccess;
import com.github.junrar.io.ReadOnlyAccessFile;
/**
* @author Rogiel
*
*/
public class FileVolume implements Volume {
private final Archive archive;
private final File file;
/**
* @param file
*/
public FileVolume(Archive archive, File file) {
this.archive = archive;
this.file = file;
}
@Override
public IReadOnlyAccess getReadOnlyAccess() throws IOException {
return new ReadOnlyAccessFile(file);
}
@Override
public long getLength() {
return file.length();
}
@Override
public Archive getArchive() {
return archive;
}
/**
* @return the file
*/
public File getFile() {
return file;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/impl/FileVolumeManager.java
================================================
/*
* This file is part of seedbox .
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see .
*/
package com.github.junrar.impl;
import java.io.File;
import java.io.IOException;
import com.github.junrar.Archive;
import com.github.junrar.Volume;
import com.github.junrar.VolumeManager;
import com.github.junrar.util.VolumeHelper;
/**
* @author Rogiel
*
*/
public class FileVolumeManager implements VolumeManager {
private final File firstVolume;
public FileVolumeManager(File firstVolume) {
this.firstVolume = firstVolume;
}
@Override
public Volume nextArchive(Archive archive, Volume last)
throws IOException {
if (last == null)
return new FileVolume(archive, firstVolume);
FileVolume lastFileVolume = (FileVolume) last;
boolean oldNumbering = !archive.getMainHeader().isNewNumbering()
|| archive.isOldFormat();
String nextName = VolumeHelper.nextVolumeName(lastFileVolume.getFile()
.getAbsolutePath(), oldNumbering);
File nextVolume = new File(nextName);
return new FileVolume(archive, nextVolume);
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/io/IReadOnlyAccess.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 23.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.io;
import java.io.IOException;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public interface IReadOnlyAccess {
/**
* @return the current position in the file
*/
public long getPosition() throws IOException;
/**
* @param pos the position in the file
* @return success ? true : false
*/
public void setPosition(long pos) throws IOException;
/** Read a single byte of data. */
public int read() throws IOException;
/**
* Read up to count bytes to the specified buffer.
*/
public int read(byte[] buffer, int off, int count) throws IOException;
/**
* Read exactly count bytes to the specified buffer.
*
* @param buffer where to store the read data
* @param count how many bytes to read
* @return bytes read || -1 if IO problem
*/
public int readFully(byte[] buffer, int count) throws IOException;
/** Close this file. */
public void close() throws IOException;
}
================================================
FILE: unrar/src/main/java/com/github/junrar/io/InputStreamReadOnlyAccessFile.java
================================================
package com.github.junrar.io;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* InputStream based implementation of the IReadOnlyAccess interface.
*
* @see http://rsbweb.nih.gov/ij/
* @author martinr
*/
public class InputStreamReadOnlyAccessFile implements IReadOnlyAccess {
private RandomAccessStream is;
/**
* Create new instance.
*
* @param is The input stream to wrap.
*/
public InputStreamReadOnlyAccessFile(final InputStream is) {
this.is = new RandomAccessStream(new BufferedInputStream(is));
}
@Override
public long getPosition() throws IOException {
return is.getLongFilePointer();
}
@Override
public void setPosition(long pos) throws IOException {
is.seek(pos);
}
@Override
public int read() throws IOException {
return is.read();
}
@Override
public int read(byte[] buffer, int off, int count) throws IOException {
return is.read(buffer, off, count);
}
@Override
public int readFully(byte[] buffer, int count) throws IOException {
is.readFully(buffer, count);
return count;
}
@Override
public void close() throws IOException {
is.close();
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/io/RandomAccessStream.java
================================================
/*
* public domain as of http://rsbweb.nih.gov/ij/disclaimer.html
*/
package com.github.junrar.io;
import java.io.*;
import java.util.Vector;
/**
* This is a class that uses a memory cache to allow seeking within an
* InputStream. Based on the JAI MemoryCacheSeekableStream class. Can also be
* constructed from a RandomAccessFile, which uses less memory since the memory
* cache is not required.
*/
@SuppressWarnings("rawtypes")
public final class RandomAccessStream extends InputStream {
private static final int BLOCK_SIZE = 512;
private static final int BLOCK_MASK = 511;
private static final int BLOCK_SHIFT = 9;
private InputStream src;
private RandomAccessFile ras;
private long pointer;
private Vector data;
private int length;
private boolean foundEOS;
/**
* Constructs a RandomAccessStream from an InputStream. Seeking backwards is
* supported using a memory cache.
*/
public RandomAccessStream(InputStream inputstream) {
pointer = 0L;
data = new Vector();
length = 0;
foundEOS = false;
src = inputstream;
}
/** Constructs a RandomAccessStream from an RandomAccessFile. */
public RandomAccessStream(RandomAccessFile ras) {
this.ras = ras;
}
public int getFilePointer() throws IOException {
if (ras != null)
return (int) ras.getFilePointer();
else
return (int) pointer;
}
public long getLongFilePointer() throws IOException {
if (ras != null)
return ras.getFilePointer();
else
return pointer;
}
public int read() throws IOException {
if (ras != null)
return ras.read();
long l = pointer + 1L;
long l1 = readUntil(l);
if (l1 >= l) {
byte abyte0[] = (byte[]) data
.elementAt((int) (pointer >> BLOCK_SHIFT));
return abyte0[(int) (pointer++ & BLOCK_MASK)] & 0xff;
} else
return -1;
}
public int read(byte[] bytes, int off, int len) throws IOException {
if (bytes == null)
throw new NullPointerException();
if (ras != null)
return ras.read(bytes, off, len);
if (off < 0 || len < 0 || off + len > bytes.length)
throw new IndexOutOfBoundsException();
if (len == 0)
return 0;
long l = readUntil(pointer + len);
if (l <= pointer)
return -1;
else {
byte abyte1[] = (byte[]) data
.elementAt((int) (pointer >> BLOCK_SHIFT));
int k = Math.min(len, BLOCK_SIZE - (int) (pointer & BLOCK_MASK));
System.arraycopy(abyte1, (int) (pointer & BLOCK_MASK), bytes, off,
k);
pointer += k;
return k;
}
}
public final void readFully(byte[] bytes) throws IOException {
readFully(bytes, bytes.length);
}
public final void readFully(byte[] bytes, int len) throws IOException {
int read = 0;
do {
int l = read(bytes, read, len - read);
if (l < 0)
break;
read += l;
} while (read < len);
}
@SuppressWarnings("unchecked")
private long readUntil(long l) throws IOException {
if (l < length)
return l;
if (foundEOS)
return length;
int i = (int) (l >> BLOCK_SHIFT);
int j = length >> BLOCK_SHIFT;
for (int k = j; k <= i; k++) {
byte abyte0[] = new byte[BLOCK_SIZE];
data.addElement(abyte0);
int i1 = BLOCK_SIZE;
int j1 = 0;
while (i1 > 0) {
int k1 = src.read(abyte0, j1, i1);
if (k1 == -1) {
foundEOS = true;
return length;
}
j1 += k1;
i1 -= k1;
length += k1;
}
}
return length;
}
public void seek(long loc) throws IOException {
if (ras != null) {
ras.seek(loc);
return;
}
if (loc < 0L)
pointer = 0L;
else
pointer = loc;
}
public void seek(int loc) throws IOException {
long lloc = ((long) loc) & 0xffffffffL;
if (ras != null) {
ras.seek(lloc);
return;
}
if (lloc < 0L)
pointer = 0L;
else
pointer = lloc;
}
public final int readInt() throws IOException {
int i = read();
int j = read();
int k = read();
int l = read();
if ((i | j | k | l) < 0)
throw new EOFException();
else
return (i << 24) + (j << 16) + (k << 8) + l;
}
public final long readLong() throws IOException {
return ((long) readInt() << 32) + ((long) readInt() & 0xffffffffL);
}
public final double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
public final short readShort() throws IOException {
int i = read();
int j = read();
if ((i | j) < 0)
throw new EOFException();
else
return (short) ((i << 8) + j);
}
public final float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
}
public void close() throws IOException {
if (ras != null)
ras.close();
else {
data.removeAllElements();
src.close();
}
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/io/Raw.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 18.06.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.io;
/**
* Read / write numbers to a byte[] regarding the endianness of the array
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class Raw {
/**
* Read a short value from the byte array at the given position (Big Endian)
*
* @param array
* the array to read from
* @param pos
* the position
* @return the value
*/
public static final short readShortBigEndian(byte[] array, int pos) {
short temp = 0;
temp |= array[pos] & 0xff;
temp <<= 8;
temp |= array[pos + 1] & 0xff;
return temp;
}
/**
* Read a int value from the byte array at the given position (Big Endian)
*
* @param array
* the array to read from
* @param pos
* the offset
* @return the value
*/
public static final int readIntBigEndian(byte[] array, int pos) {
int temp = 0;
temp |= array[pos] & 0xff;
temp <<= 8;
temp |= array[pos + 1] & 0xff;
temp <<= 8;
temp |= array[pos + 2] & 0xff;
temp <<= 8;
temp |= array[pos + 3] & 0xff;
return temp;
}
/**
* Read a long value from the byte array at the given position (Big Endian)
*
* @param array
* the array to read from
* @param pos
* the offset
* @return the value
*/
public static final long readLongBigEndian(byte[] array, int pos) {
int temp = 0;
temp |= array[pos] & 0xff;
temp <<= 8;
temp |= array[pos + 1] & 0xff;
temp <<= 8;
temp |= array[pos + 2] & 0xff;
temp <<= 8;
temp |= array[pos + 3] & 0xff;
temp <<= 8;
temp |= array[pos + 4] & 0xff;
temp <<= 8;
temp |= array[pos + 5] & 0xff;
temp <<= 8;
temp |= array[pos + 6] & 0xff;
temp <<= 8;
temp |= array[pos + 7] & 0xff;
return temp;
}
/**
* Read a short value from the byte array at the given position (little
* Endian)
*
* @param array
* the array to read from
* @param pos
* the offset
* @return the value
*/
public static final short readShortLittleEndian(byte[] array, int pos) {
short result = 0;
result += array[pos + 1] & 0xff;
result <<= 8;
result += array[pos] & 0xff;
return result;
}
/**
* Read an int value from the byte array at the given position (little
* Endian)
*
* @param array
* the array to read from
* @param pos
* the offset
* @return the value
*/
public static final int readIntLittleEndian(byte[] array, int pos) {
return ((array[pos + 3] & 0xff) << 24)
| ((array[pos + 2] & 0xff) << 16)
| ((array[pos + 1] & 0xff) << 8) | ((array[pos] & 0xff));
}
/**
* Read an long value(unsigned int) from the byte array at the given
* position (little Endian)
*
* @param array
* @param pos
* @return
*/
public static final long readIntLittleEndianAsLong(byte[] array, int pos) {
return (((long) array[pos + 3] & 0xff) << 24)
| (((long) array[pos + 2] & 0xff) << 16)
| (((long) array[pos + 1] & 0xff) << 8)
| (((long) array[pos] & 0xff));
}
/**
* Read a long value from the byte array at the given position (little
* Endian)
*
* @param array
* the array to read from
* @param pos
* the offset
* @return the value
*/
public static final long readLongLittleEndian(byte[] array, int pos) {
int temp = 0;
temp |= array[pos + 7] & 0xff;
temp <<= 8;
temp |= array[pos + 6] & 0xff;
temp <<= 8;
temp |= array[pos + 5] & 0xff;
temp <<= 8;
temp |= array[pos + 4] & 0xff;
temp <<= 8;
temp |= array[pos + 3] & 0xff;
temp <<= 8;
temp |= array[pos + 2] & 0xff;
temp <<= 8;
temp |= array[pos + 1] & 0xff;
temp <<= 8;
temp |= array[pos];
return temp;
}
/**
* Write a short value into the byte array at the given position (Big
* endian)
*
* @param array
* the array
* @param pos
* the offset
* @param value
* the value to write
*/
public static final void writeShortBigEndian(byte[] array, int pos,
short value) {
array[pos] = (byte) (value >>> 8);
array[pos + 1] = (byte) (value & 0xFF);
}
/**
* Write an int value into the byte array at the given position (Big endian)
*
* @param array
* the array
* @param pos
* the offset
* @param value
* the value to write
*/
public static final void writeIntBigEndian(byte[] array, int pos, int value) {
array[pos] = (byte) ((value >>> 24) & 0xff);
array[pos + 1] = (byte) ((value >>> 16) & 0xff);
array[pos + 2] = (byte) ((value >>> 8) & 0xff);
array[pos + 3] = (byte) ((value) & 0xff);
}
/**
* Write a long value into the byte array at the given position (Big endian)
*
* @param array
* the array
* @param pos
* the offset
* @param value
* the value to write
*/
public static final void writeLongBigEndian(byte[] array, int pos,
long value) {
array[pos] = (byte) (value >>> 56);
array[pos + 1] = (byte) (value >>> 48);
array[pos + 2] = (byte) (value >>> 40);
array[pos + 3] = (byte) (value >>> 32);
array[pos + 4] = (byte) (value >>> 24);
array[pos + 5] = (byte) (value >>> 16);
array[pos + 6] = (byte) (value >>> 8);
array[pos + 7] = (byte) (value & 0xFF);
}
/**
* Write a short value into the byte array at the given position (little
* endian)
*
* @param array
* the array
* @param pos
* the offset
* @param value
* the value to write
*/
public static final void writeShortLittleEndian(byte[] array, int pos,
short value) {
array[pos + 1] = (byte) (value >>> 8);
array[pos] = (byte) (value & 0xFF);
}
/**
* Increment a short value at the specified position by the specified amount
* (little endian).
*/
public static final void incShortLittleEndian(byte[] array, int pos, int dv) {
int c = ((array[pos] & 0xff) + (dv & 0xff)) >>> 8;
array[pos] += dv & 0xff;
if ((c > 0) || ((dv & 0xff00) != 0)) {
array[pos + 1] += ((dv >>> 8) & 0xff) + c;
}
}
/**
* Write an int value into the byte array at the given position (little
* endian)
*
* @param array
* the array
* @param pos
* the offset
* @param value
* the value to write
*/
public static final void writeIntLittleEndian(byte[] array, int pos,
int value) {
array[pos + 3] = (byte) (value >>> 24);
array[pos + 2] = (byte) (value >>> 16);
array[pos + 1] = (byte) (value >>> 8);
array[pos] = (byte) (value & 0xFF);
}
/**
* Write a long value into the byte array at the given position (little
* endian)
*
* @param array
* the array
* @param pos
* the offset
* @param value
* the value to write
*/
public static final void writeLongLittleEndian(byte[] array, int pos,
long value) {
array[pos + 7] = (byte) (value >>> 56);
array[pos + 6] = (byte) (value >>> 48);
array[pos + 5] = (byte) (value >>> 40);
array[pos + 4] = (byte) (value >>> 32);
array[pos + 3] = (byte) (value >>> 24);
array[pos + 2] = (byte) (value >>> 16);
array[pos + 1] = (byte) (value >>> 8);
array[pos] = (byte) (value & 0xFF);
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/io/ReadOnlyAccessByteArray.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 30.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.io;
import java.io.EOFException;
import java.io.IOException;
/**
* A File like access to a byte array.
* (seek and read certain number of bytes)
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class ReadOnlyAccessByteArray implements IReadOnlyAccess{
private int positionInFile;
private byte[] file;
/**
* Initialize with byte[ ]
* @param file the file given as byte array
*/
public ReadOnlyAccessByteArray(byte[] file){
if(file == null){
throw new NullPointerException("file must not be null!!");
}
this.file = file;
this.positionInFile = 0;
}
public long getPosition() throws IOException {
return positionInFile;
}
public void setPosition(long pos) throws IOException {
if (pos < file.length && pos >= 0){
this.positionInFile = (int)pos;
}
else{
throw new EOFException();
}
}
/** Read a single byte of data. */
public int read() throws IOException {
return file[positionInFile++];
}
/**
* Read up to count bytes to the specified buffer.
*/
public int read(byte[] buffer, int off, int count) throws IOException {
int read = Math.min(count, file.length-positionInFile);
System.arraycopy(file, positionInFile, buffer, off, read);
positionInFile += read;
return read;
}
public int readFully(byte[] buffer, int count) throws IOException {
if(buffer == null ){
throw new NullPointerException("buffer must not be null");
}
if(count == 0){
throw new IllegalArgumentException("cannot read 0 bytes ;-)");
}
int read = Math.min(count, file.length-(int)positionInFile-1);
System.arraycopy(file, (int)positionInFile, buffer, 0, read );
positionInFile+=read;
return read;
}
public void close() throws IOException {
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/io/ReadOnlyAccessFile.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 23.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.io;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class ReadOnlyAccessFile extends RandomAccessFile
implements IReadOnlyAccess{
/**
* @param file the file
* @throws FileNotFoundException
*/
public ReadOnlyAccessFile(File file) throws FileNotFoundException {
super(file, "r");
}
public int readFully(byte[] buffer, int count) throws IOException {
assert (count > 0) : count;
this.readFully(buffer, 0, count);
return count;
}
public long getPosition() throws IOException {
return this.getFilePointer();
}
public void setPosition(long pos) throws IOException {
this.seek(pos);
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/io/ReadOnlyAccessInputStream.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 26.06.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.io;
import java.io.IOException;
import java.io.InputStream;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class ReadOnlyAccessInputStream extends InputStream {
private IReadOnlyAccess file;
private long curPos;
private final long startPos;
private final long endPos;
public ReadOnlyAccessInputStream(IReadOnlyAccess file, long startPos,
long endPos) throws IOException {
super();
this.file = file;
this.startPos = startPos;
curPos = startPos;
this.endPos = endPos;
file.setPosition(curPos);
}
@Override
public int read() throws IOException {
if (curPos == endPos) {
return -1;
}
else {
int b = file.read();
curPos++;
return b;
}
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (len == 0) {
return 0;
}
if (curPos == endPos) {
return -1;
}
int bytesRead = file.read(b, off,
(int)Math.min(len, endPos - curPos));
curPos += bytesRead;
return bytesRead;
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
//
// public void close() throws IOException {
// file.close();
// }
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/AVHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 24.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.rarfile;
import com.github.junrar.io.Raw;
/**
* extended version info header
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class AVHeader extends BaseBlock {
public static final int avHeaderSize = 7;
private byte unpackVersion;
private byte method;
private byte avVersion;
private int avInfoCRC;
public AVHeader(BaseBlock bb, byte[] avHeader){
super(bb);
int pos =0;
unpackVersion |= avHeader[pos]&0xff;
pos++;
method |= avHeader[pos]&0xff;
pos++;
avVersion |= avHeader[pos]&0xff;
pos++;
avInfoCRC = Raw.readIntLittleEndian(avHeader, pos);
}
public int getAvInfoCRC() {
return avInfoCRC;
}
public byte getAvVersion() {
return avVersion;
}
public byte getMethod() {
return method;
}
public byte getUnpackVersion() {
return unpackVersion;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/BaseBlock.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 22.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.rarfile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.junrar.io.Raw;
/**
* Base class of all rar headers
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class BaseBlock{
Log logger = LogFactory.getLog(BaseBlock.class.getName());
public static final short BaseBlockSize = 7;
//TODO move somewhere else
public static final short MHD_VOLUME = 0x0001;
public static final short MHD_COMMENT = 0x0002;
public static final short MHD_LOCK = 0x0004;
public static final short MHD_SOLID = 0x0008;
public static final short MHD_PACK_COMMENT = 0x0010;
public static final short MHD_NEWNUMBERING = 0x0010;
public static final short MHD_AV = 0x0020;
public static final short MHD_PROTECT = 0x0040;
public static final short MHD_PASSWORD = 0x0080;
public static final short MHD_FIRSTVOLUME = 0x0100;
public static final short MHD_ENCRYPTVER = 0x0200;
public static final short LHD_SPLIT_BEFORE = 0x0001;
public static final short LHD_SPLIT_AFTER = 0x0002;
public static final short LHD_PASSWORD = 0x0004;
public static final short LHD_COMMENT = 0x0008;
public static final short LHD_SOLID = 0x0010;
public static final short LHD_WINDOWMASK = 0x00e0;
public static final short LHD_WINDOW64 = 0x0000;
public static final short LHD_WINDOW128 = 0x0020;
public static final short LHD_WINDOW256 = 0x0040;
public static final short LHD_WINDOW512 = 0x0060;
public static final short LHD_WINDOW1024 = 0x0080;
public static final short LHD_WINDOW2048 = 0x00a0;
public static final short LHD_WINDOW4096 = 0x00c0;
public static final short LHD_DIRECTORY = 0x00e0;
public static final short LHD_LARGE = 0x0100;
public static final short LHD_UNICODE = 0x0200;
public static final short LHD_SALT = 0x0400;
public static final short LHD_VERSION = 0x0800;
public static final short LHD_EXTTIME = 0x1000;
public static final short LHD_EXTFLAGS = 0x2000;
public static final short SKIP_IF_UNKNOWN = 0x4000;
public static final short LONG_BLOCK = -0x8000;
public static final short EARC_NEXT_VOLUME = 0x0001;
public static final short EARC_DATACRC = 0x0002;
public static final short EARC_REVSPACE = 0x0004;
public static final short EARC_VOLNUMBER = 0x0008;
protected long positionInFile;
protected short headCRC = 0;
protected byte headerType = 0;
protected short flags = 0;
protected short headerSize = 0 ;
/**
*
*/
public BaseBlock(){
}
public BaseBlock(BaseBlock bb){
this.flags = bb.getFlags();
this.headCRC = bb.getHeadCRC();
this.headerType = bb.getHeaderType().getHeaderByte();
this.headerSize = bb.getHeaderSize();
this.positionInFile = bb.getPositionInFile();
}
public BaseBlock(byte[] baseBlockHeader){
int pos = 0;
this.headCRC = Raw.readShortLittleEndian(baseBlockHeader, pos);
pos+=2;
this.headerType |= baseBlockHeader[pos]&0xff;
pos++;
this.flags = Raw.readShortLittleEndian(baseBlockHeader, pos);
pos+=2;
this.headerSize = Raw.readShortLittleEndian(baseBlockHeader, pos);
}
public boolean hasArchiveDataCRC(){
return (this.flags & EARC_DATACRC)!=0;
}
public boolean hasVolumeNumber(){
return (this.flags & EARC_VOLNUMBER)!=0;
}
public boolean hasEncryptVersion(){
return (flags & MHD_ENCRYPTVER)!=0;
}
/**
* @return is it a sub block
*/
public boolean isSubBlock()
{
if (UnrarHeadertype.SubHeader.equals(headerType)){
return(true);
}
if (UnrarHeadertype.NewSubHeader.equals(headerType) && (flags & LHD_SOLID)!=0)
{
return(true);
}
return(false);
}
public long getPositionInFile() {
return positionInFile;
}
public short getFlags() {
return flags;
}
public short getHeadCRC() {
return headCRC;
}
public short getHeaderSize() {
return headerSize;
}
public UnrarHeadertype getHeaderType() {
return UnrarHeadertype.findType(headerType);
}
public void setPositionInFile(long positionInFile) {
this.positionInFile = positionInFile;
}
public void print(){
StringBuilder str =new StringBuilder();
str.append("HeaderType: " + getHeaderType());
str.append("\nHeadCRC: "+Integer.toHexString(getHeadCRC()));
str.append("\nFlags: "+Integer.toHexString(getFlags()));
str.append("\nHeaderSize: "+getHeaderSize());
str.append("\nPosition in file: "+getPositionInFile());
logger.info(str.toString());
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/BlockHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 22.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.rarfile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.junrar.io.Raw;
/**
* Base class of headers that contain data
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class BlockHeader extends BaseBlock{
public static final short blockHeaderSize = 4;
private Log logger = LogFactory.getLog(BlockHeader.class.getName());
private int dataSize;
private int packSize;
public BlockHeader(){
}
public BlockHeader(BlockHeader bh){
super(bh);
this.packSize = bh.getDataSize();
this.dataSize = packSize;
this.positionInFile = bh.getPositionInFile();
}
public BlockHeader(BaseBlock bb, byte[] blockHeader)
{
super(bb);
this.packSize = Raw.readIntLittleEndian(blockHeader, 0);
this.dataSize = this.packSize;
}
public int getDataSize() {
return dataSize;
}
public int getPackSize() {
return packSize;
}
public void print(){
super.print();
String s = "DataSize: "+getDataSize()+" packSize: "+getPackSize();
logger.info(s);
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/CommentHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 23.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.rarfile;
import com.github.junrar.io.Raw;
/**
* Comment header
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class CommentHeader extends BaseBlock {
public static final short commentHeaderSize = 6;
private short unpSize;
private byte unpVersion;
private byte unpMethod;
private short commCRC;
public CommentHeader(BaseBlock bb, byte[] commentHeader){
super(bb);
int pos =0;
unpSize = Raw.readShortLittleEndian(commentHeader, pos);
pos += 2;
unpVersion |= commentHeader[pos]&0xff;
pos++;
unpMethod |= commentHeader[pos]&0xff;
pos++;
commCRC =Raw.readShortLittleEndian(commentHeader, pos);
}
public short getCommCRC() {
return commCRC;
}
public byte getUnpMethod() {
return unpMethod;
}
public short getUnpSize() {
return unpSize;
}
public byte getUnpVersion() {
return unpVersion;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/EAHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 27.11.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.rarfile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.junrar.io.Raw;
/**
* extended archive CRC header
*
*/
public class EAHeader
extends SubBlockHeader
{
private Log logger = LogFactory.getLog(getClass());
public static final short EAHeaderSize = 10;
private int unpSize;
private byte unpVer;
private byte method;
private int EACRC;
public EAHeader(SubBlockHeader sb, byte[] eahead)
{
super(sb);
int pos = 0;
unpSize = Raw.readIntLittleEndian(eahead, pos);
pos+=4;
unpVer |= eahead[pos]&0xff;
pos++;
method |= eahead[pos]&0xff;
pos++;
EACRC = Raw.readIntLittleEndian(eahead, pos);
}
/**
* @return the eACRC
*/
public int getEACRC() {
return EACRC;
}
/**
* @return the method
*/
public byte getMethod() {
return method;
}
/**
* @return the unpSize
*/
public int getUnpSize() {
return unpSize;
}
/**
* @return the unpVer
*/
public byte getUnpVer() {
return unpVer;
}
public void print()
{
super.print();
logger.info("unpSize: "+unpSize);
logger.info("unpVersion: " + unpVer);
logger.info("method: "+method);
logger.info("EACRC:" + EACRC);
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/EndArcHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 24.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.rarfile;
import com.github.junrar.io.Raw;
/**
*
* the optional End header
*
*/
public class EndArcHeader extends BaseBlock{
private static final short EARC_NEXT_VOLUME = 0x0001;
private static final short EARC_DATACRC = 0x0002;
private static final short EARC_REVSPACE = 0x0004;
private static final short EARC_VOLNUMBER = 0x0008;
private static final short endArcHeaderSize = 6;
public static final short endArcArchiveDataCrcSize = 4;
public static final short endArcVolumeNumberSize = 2;
private int archiveDataCRC;
private short volumeNumber;
public EndArcHeader(BaseBlock bb, byte[] endArcHeader){
super(bb);
int pos = 0;
if(hasArchiveDataCRC()){
archiveDataCRC =Raw.readIntLittleEndian(endArcHeader, pos);
pos+=4;
}
if(hasVolumeNumber()){
volumeNumber = Raw.readShortLittleEndian(endArcHeader, pos);
}
}
public int getArchiveDataCRC() {
return archiveDataCRC;
}
public short getVolumeNumber() {
return volumeNumber;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/FileHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 22.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.rarfile;
import java.util.Calendar;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.junrar.io.Raw;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class FileHeader extends BlockHeader {
private final Log logger = LogFactory.getLog(FileHeader.class.getName());
private static final byte SALT_SIZE = 8;
private static final byte NEWLHD_SIZE = 32;
private long unpSize;
private final HostSystem hostOS;
private final int fileCRC;
private final int fileTime;
private byte unpVersion;
private byte unpMethod;
private short nameSize;
private int highPackSize;
private int highUnpackSize;
private final byte[] fileNameBytes;
private String fileName;
private String fileNameW;
private byte[] subData;
private final byte[] salt = new byte[SALT_SIZE];
private Date mTime;
private Date cTime;
private Date aTime;
private Date arcTime;
private long fullPackSize;
private long fullUnpackSize;
private int fileAttr;
private int subFlags; // same as fileAttr (in header)
private int recoverySectors = -1;
public FileHeader(BlockHeader bh, byte[] fileHeader) {
super(bh);
int position = 0;
unpSize = Raw.readIntLittleEndianAsLong(fileHeader, position);
position += 4;
hostOS = HostSystem.findHostSystem(fileHeader[4]);
position++;
fileCRC = Raw.readIntLittleEndian(fileHeader, position);
position += 4;
fileTime = Raw.readIntLittleEndian(fileHeader, position);
position += 4;
unpVersion |= fileHeader[13] & 0xff;
position++;
unpMethod |= fileHeader[14] & 0xff;
position++;
nameSize = Raw.readShortLittleEndian(fileHeader, position);
position += 2;
fileAttr = Raw.readIntLittleEndian(fileHeader, position);
position += 4;
if (isLargeBlock()) {
highPackSize = Raw.readIntLittleEndian(fileHeader, position);
position += 4;
highUnpackSize = Raw.readIntLittleEndian(fileHeader, position);
position += 4;
} else {
highPackSize = 0;
highUnpackSize = 0;
if (unpSize == 0xffffffff) {
unpSize = 0xffffffff;
highUnpackSize = Integer.MAX_VALUE;
}
}
fullPackSize |= highPackSize;
fullPackSize <<= 32;
fullPackSize |= getPackSize();
fullUnpackSize |= highUnpackSize;
fullUnpackSize <<= 32;
fullUnpackSize += unpSize;
nameSize = nameSize > 4 * 1024 ? 4 * 1024 : nameSize;
fileNameBytes = new byte[nameSize];
for (int i = 0; i < nameSize; i++) {
fileNameBytes[i] = fileHeader[position];
position++;
}
if (isFileHeader()) {
if (isUnicode()) {
int length = 0;
fileName = "";
fileNameW = "";
while (length < fileNameBytes.length
&& fileNameBytes[length] != 0) {
length++;
}
byte[] name = new byte[length];
System.arraycopy(fileNameBytes, 0, name, 0, name.length);
fileName = new String(name);
if (length != nameSize) {
length++;
fileNameW = FileNameDecoder.decode(fileNameBytes, length);
}
} else {
fileName = new String(fileNameBytes);
fileNameW = "";
}
}
if (UnrarHeadertype.NewSubHeader.equals(headerType)) {
int datasize = headerSize - NEWLHD_SIZE - nameSize;
if (hasSalt()) {
datasize -= SALT_SIZE;
}
if (datasize > 0) {
subData = new byte[datasize];
for (int i = 0; i < datasize; i++) {
subData[i] = (fileHeader[position]);
position++;
}
}
if (NewSubHeaderType.SUBHEAD_TYPE_RR.byteEquals(fileNameBytes)) {
recoverySectors = subData[8] + (subData[9] << 8)
+ (subData[10] << 16) + (subData[11] << 24);
}
}
if (hasSalt()) {
for (int i = 0; i < SALT_SIZE; i++) {
salt[i] = fileHeader[position];
position++;
}
}
mTime = getDateDos(fileTime);
// TODO rartime -> extended
}
@Override
public void print() {
super.print();
StringBuilder str = new StringBuilder();
str.append("unpSize: " + getUnpSize());
str.append("\nHostOS: " + hostOS.name());
str.append("\nMDate: " + mTime);
str.append("\nFileName: " + getFileNameString());
str.append("\nunpMethod: " + Integer.toHexString(getUnpMethod()));
str.append("\nunpVersion: " + Integer.toHexString(getUnpVersion()));
str.append("\nfullpackedsize: " + getFullPackSize());
str.append("\nfullunpackedsize: " + getFullUnpackSize());
str.append("\nisEncrypted: " + isEncrypted());
str.append("\nisfileHeader: " + isFileHeader());
str.append("\nisSolid: " + isSolid());
str.append("\nisSplitafter: " + isSplitAfter());
str.append("\nisSplitBefore:" + isSplitBefore());
str.append("\nunpSize: " + getUnpSize());
str.append("\ndataSize: " + getDataSize());
str.append("\nisUnicode: " + isUnicode());
str.append("\nhasVolumeNumber: " + hasVolumeNumber());
str.append("\nhasArchiveDataCRC: " + hasArchiveDataCRC());
str.append("\nhasSalt: " + hasSalt());
str.append("\nhasEncryptVersions: " + hasEncryptVersion());
str.append("\nisSubBlock: " + isSubBlock());
logger.info(str.toString());
}
private Date getDateDos(int time) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, (time >>> 25) + 1980);
cal.set(Calendar.MONTH, ((time >>> 21) & 0x0f) - 1);
cal.set(Calendar.DAY_OF_MONTH, (time >>> 16) & 0x1f);
cal.set(Calendar.HOUR_OF_DAY, (time >>> 11) & 0x1f);
cal.set(Calendar.MINUTE, (time >>> 5) & 0x3f);
cal.set(Calendar.SECOND, (time & 0x1f) * 2);
return cal.getTime();
}
public Date getArcTime() {
return arcTime;
}
public void setArcTime(Date arcTime) {
this.arcTime = arcTime;
}
public Date getATime() {
return aTime;
}
public void setATime(Date time) {
aTime = time;
}
public Date getCTime() {
return cTime;
}
public void setCTime(Date time) {
cTime = time;
}
public int getFileAttr() {
return fileAttr;
}
public void setFileAttr(int fileAttr) {
this.fileAttr = fileAttr;
}
public int getFileCRC() {
return fileCRC;
}
public byte[] getFileNameByteArray() {
return fileNameBytes;
}
public String getFileNameString() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFileNameW() {
return fileNameW;
}
public void setFileNameW(String fileNameW) {
this.fileNameW = fileNameW;
}
public int getHighPackSize() {
return highPackSize;
}
public int getHighUnpackSize() {
return highUnpackSize;
}
public HostSystem getHostOS() {
return hostOS;
}
public Date getMTime() {
return mTime;
}
public void setMTime(Date time) {
mTime = time;
}
public short getNameSize() {
return nameSize;
}
public int getRecoverySectors() {
return recoverySectors;
}
public byte[] getSalt() {
return salt;
}
public byte[] getSubData() {
return subData;
}
public int getSubFlags() {
return subFlags;
}
public byte getUnpMethod() {
return unpMethod;
}
public long getUnpSize() {
return unpSize;
}
public byte getUnpVersion() {
return unpVersion;
}
public long getFullPackSize() {
return fullPackSize;
}
public long getFullUnpackSize() {
return fullUnpackSize;
}
@Override
public String toString() {
return super.toString();
}
/**
* the file will be continued in the next archive part
*
* @return
*/
public boolean isSplitAfter() {
return (this.flags & BlockHeader.LHD_SPLIT_AFTER) != 0;
}
/**
* the file is continued in this archive
*
* @return
*/
public boolean isSplitBefore() {
return (this.flags & LHD_SPLIT_BEFORE) != 0;
}
/**
* this file is compressed as solid (all files handeled as one)
*
* @return
*/
public boolean isSolid() {
return (this.flags & LHD_SOLID) != 0;
}
/**
* the file is encrypted
*
* @return
*/
public boolean isEncrypted() {
return (this.flags & BlockHeader.LHD_PASSWORD) != 0;
}
/**
* the filename is also present in unicode
*
* @return
*/
public boolean isUnicode() {
return (flags & LHD_UNICODE) != 0;
}
public boolean isFileHeader() {
return UnrarHeadertype.FileHeader.equals(headerType);
}
public boolean hasSalt() {
return (flags & LHD_SALT) != 0;
}
public boolean isLargeBlock() {
return (flags & LHD_LARGE) != 0;
}
/**
* whether this fileheader represents a directory
*
* @return
*/
public boolean isDirectory() {
return (flags & LHD_WINDOWMASK) == LHD_DIRECTORY;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/FileNameDecoder.java
================================================
/*
*
* Original author: alpha_lam
* Creation date: ?
*
* 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.rarfile;
public class FileNameDecoder {
public static int getChar(byte [] name,int pos){
return name[pos]&0xff;
}
public static String decode(byte [] name,int encPos){
int decPos = 0;
int flags = 0;
int flagBits = 0;
int low = 0;
int high = 0;
int highByte = getChar(name,encPos++);
StringBuffer buf = new StringBuffer();
while(encPos < name.length){
if(flagBits == 0){
flags = getChar(name,encPos++);
flagBits = 8;
}
switch(flags >> 6){
case 0:
buf.append((char)(getChar(name,encPos++)));
++decPos;
break;
case 1:
buf.append((char)(getChar(name,encPos++)+(highByte<<8)));
++decPos;
break;
case 2:
low = getChar(name,encPos);
high = getChar(name,encPos+1);
buf.append((char)((high << 8) + low));
++decPos;
encPos += 2;
break;
case 3:
int length = getChar(name,encPos++);
if((length&0x80)!=0){
int correction = getChar(name,encPos++);
for(length=(length&0x7f)+2;length>0&&decPos0&&decPos": ">" or ">"
* "@": "@"
*/
package com.github.junrar.rarfile;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public enum HostSystem {
msdos ((byte)0),
os2 ((byte)1),
win32 ((byte)2),
unix ((byte)3),
macos ((byte)4),
beos ((byte)5);
private byte hostByte;
public static HostSystem findHostSystem(byte hostByte){
if(HostSystem.msdos.equals(hostByte)){
return HostSystem.msdos;
}
if(HostSystem.os2.equals(hostByte)){
return HostSystem.os2;
}
if(HostSystem.win32.equals(hostByte)){
return HostSystem.win32;
}
if(HostSystem.unix.equals(hostByte)){
return HostSystem.unix;
}
if(HostSystem.macos.equals(hostByte)){
return HostSystem.macos;
}
if(HostSystem.beos.equals(hostByte)){
return HostSystem.beos;
}
return null;
}
private HostSystem(byte hostByte){
this.hostByte = hostByte;
}
public boolean equals(byte hostByte){
return this.hostByte == hostByte;
}
public byte getHostByte(){
return hostByte;
}
//???? public static final byte max = 6;
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/MacInfoHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 26.11.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.rarfile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.junrar.io.Raw;
/**
* Mac File attribute header
*
*/
public class MacInfoHeader
extends SubBlockHeader
{
private Log logger = LogFactory.getLog(getClass());
public static final short MacInfoHeaderSize = 8;
private int fileType;
private int fileCreator;
public MacInfoHeader(SubBlockHeader sb, byte[] macHeader)
{
super(sb);
int pos = 0;
fileType = Raw.readIntLittleEndian(macHeader, pos);
pos+=4;
fileCreator = Raw.readIntLittleEndian(macHeader, pos);
}
/**
* @return the fileCreator
*/
public int getFileCreator() {
return fileCreator;
}
/**
* @param fileCreator the fileCreator to set
*/
public void setFileCreator(int fileCreator) {
this.fileCreator = fileCreator;
}
/**
* @return the fileType
*/
public int getFileType() {
return fileType;
}
/**
* @param fileType the fileType to set
*/
public void setFileType(int fileType) {
this.fileType = fileType;
}
public void print(){
super.print();
logger.info("filetype: "+fileType);
logger.info("creator :"+fileCreator);
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/MainHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 22.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.rarfile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.junrar.io.Raw;
/**
* The main header of an rar archive. holds information concerning the whole archive (solid, encrypted etc).
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class MainHeader extends BaseBlock {
private Log logger = LogFactory.getLog(MainHeader.class.getName());
public static final short mainHeaderSizeWithEnc = 7;
public static final short mainHeaderSize = 6;
private short highPosAv;
private int posAv;
private byte encryptVersion;
public MainHeader(BaseBlock bb, byte[] mainHeader) {
super(bb);
int pos = 0;
highPosAv = Raw.readShortLittleEndian(mainHeader, pos);
pos += 2;
posAv = Raw.readIntLittleEndian(mainHeader, pos);
pos+=4;
if(hasEncryptVersion()){
encryptVersion |= mainHeader[pos]&0xff;
}
}
/**
* old cmt block is present
* @return true if has cmt block
*/
public boolean hasArchCmt(){
return (this.flags & BaseBlock.MHD_COMMENT)!=0;
}
/**
* the version the the encryption
* @return
*/
public byte getEncryptVersion() {
return encryptVersion;
}
public short getHighPosAv() {
return highPosAv;
}
public int getPosAv() {
return posAv;
}
/**
* returns whether the archive is encrypted
* @return
*/
public boolean isEncrypted(){
return (this.flags & BaseBlock.MHD_PASSWORD)!=0;
}
/**
* return whether the archive is a multivolume archive
* @return
*/
public boolean isMultiVolume(){
return (this.flags & BaseBlock.MHD_VOLUME)!=0;
}
/**
* if the archive is a multivolume archive this method returns whether this instance is the first part of the multivolume archive
* @return
*/
public boolean isFirstVolume(){
return (this.flags & BaseBlock.MHD_FIRSTVOLUME)!=0;
}
public void print(){
super.print();
StringBuilder str=new StringBuilder();
str.append("posav: "+getPosAv());
str.append("\nhighposav: "+getHighPosAv());
str.append("\nhasencversion: "+hasEncryptVersion()+(hasEncryptVersion()?getEncryptVersion():""));
str.append("\nhasarchcmt: "+hasArchCmt());
str.append("\nisEncrypted: "+isEncrypted());
str.append("\nisMultivolume: "+isMultiVolume());
str.append("\nisFirstvolume: "+isFirstVolume());
str.append("\nisSolid: "+isSolid());
str.append("\nisLocked: "+isLocked());
str.append("\nisProtected: "+isProtected());
str.append("\nisAV: "+isAV());
logger.info(str.toString());
}
/**
* returns whether this archive is solid. in this case you can only extract all file at once
* @return
*/
public boolean isSolid(){
return (this.flags&MHD_SOLID)!=0;
}
public boolean isLocked(){
return (this.flags&MHD_LOCK)!=0;
}
public boolean isProtected(){
return (this.flags&MHD_PROTECT)!=0;
}
public boolean isAV(){
return (this.flags&MHD_AV)!=0;
}
/**
* the numbering format a multivolume archive
* @return
*/
public boolean isNewNumbering(){
return (this.flags&MHD_NEWNUMBERING)!=0;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/MarkHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 24.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.rarfile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.junrar.io.Raw;
/**
* the header to recognize a file to be a rar archive
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class MarkHeader extends BaseBlock {
private Log logger = LogFactory.getLog(MarkHeader.class.getName());
private boolean oldFormat = false;
public MarkHeader(BaseBlock bb){
super(bb);
}
public boolean isValid(){
if(!(getHeadCRC() == 0x6152)){
return false;
}
if(!(getHeaderType() == UnrarHeadertype.MarkHeader)){
return false;
}
if(!(getFlags() == 0x1a21)){
return false;
}
if(!(getHeaderSize() == BaseBlockSize)){
return false;
}
return true;
}
public boolean isSignature() {
boolean valid=false;
byte[] d = new byte[BaseBlock.BaseBlockSize];
Raw.writeShortLittleEndian(d, 0, headCRC);
d[2] = headerType;
Raw.writeShortLittleEndian(d, 3, flags);
Raw.writeShortLittleEndian(d, 5, headerSize);
if (d[0] == 0x52) {
if (d[1]==0x45 && d[2]==0x7e && d[3]==0x5e) {
oldFormat=true;
valid=true;
}
else if (d[1]==0x61 && d[2]==0x72 && d[3]==0x21 && d[4]==0x1a &&
d[5]==0x07 && d[6]==0x00) {
oldFormat=false;
valid=true;
}
}
return valid;
}
public boolean isOldFormat() {
return oldFormat;
}
public void print(){
super.print();
logger.info("valid: "+isValid());
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/NewSubHeaderType.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 24.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.rarfile;
import java.util.Arrays;
/**
* subheaders new version of the info headers
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class NewSubHeaderType {
/**
* comment subheader
*/
public static final NewSubHeaderType SUBHEAD_TYPE_CMT = new NewSubHeaderType(new byte[]{'C','M','T'});
/**
*
*/
public static final NewSubHeaderType SUBHEAD_TYPE_ACL = new NewSubHeaderType(new byte[]{'A','C','L'});
/**
*
*/
public static final NewSubHeaderType SUBHEAD_TYPE_STREAM = new NewSubHeaderType(new byte[]{'S','T','M'});
/**
*
*/
public static final NewSubHeaderType SUBHEAD_TYPE_UOWNER = new NewSubHeaderType(new byte[]{'U','O','W'});
/**
*
*/
public static final NewSubHeaderType SUBHEAD_TYPE_AV = new NewSubHeaderType(new byte[]{'A','V'});
/**
* recovery record subheader
*/
public static final NewSubHeaderType SUBHEAD_TYPE_RR = new NewSubHeaderType(new byte[]{'R','R'});
/**
*
*/
public static final NewSubHeaderType SUBHEAD_TYPE_OS2EA = new NewSubHeaderType(new byte[]{'E','A','2'});
/**
*
*/
public static final NewSubHeaderType SUBHEAD_TYPE_BEOSEA = new NewSubHeaderType(new byte[]{'E','A','B','E'});
private byte[] headerTypes;
/**
* Private constructor
* @param headerTypes
*/
private NewSubHeaderType(byte[] headerTypes)
{
this.headerTypes = headerTypes;
}
/**
* @param toCompare
* @return Returns true if the given byte array matches to the internal byte array of this header.
*/
public boolean byteEquals(byte[] toCompare)
{
return Arrays.equals(this.headerTypes, toCompare);
}
@Override
public String toString()
{
return new String(this.headerTypes);
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/ProtectHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 24.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.rarfile;
import com.github.junrar.io.Raw;
/**
* recovery header
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class ProtectHeader extends BlockHeader {
/**
* the header size
*/
public static final int protectHeaderSize = 8;
private byte version;
private short recSectors;
private int totalBlocks;
private byte mark;
public ProtectHeader(BlockHeader bh, byte[] protectHeader){
super(bh);
int pos = 0;
version |= protectHeader[pos]&0xff;
recSectors = Raw.readShortLittleEndian(protectHeader, pos);
pos += 2;
totalBlocks = Raw.readIntLittleEndian(protectHeader, pos);
pos += 4;
mark |= protectHeader[pos]&0xff;
}
public byte getMark() {
return mark;
}
public short getRecSectors() {
return recSectors;
}
public int getTotalBlocks() {
return totalBlocks;
}
public byte getVersion() {
return version;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/SignHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 24.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.rarfile;
import com.github.junrar.io.Raw;
/**
* sign header
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class SignHeader extends BaseBlock {
public static final short signHeaderSize = 8;
private int creationTime=0;
private short arcNameSize=0;
private short userNameSize=0;
public SignHeader(BaseBlock bb, byte[] signHeader){
super(bb);
int pos = 0;
creationTime = Raw.readIntLittleEndian(signHeader, pos);
pos +=4;
arcNameSize = Raw.readShortLittleEndian(signHeader, pos);
pos+=2;
userNameSize = Raw.readShortLittleEndian(signHeader, pos);
}
public short getArcNameSize() {
return arcNameSize;
}
public int getCreationTime() {
return creationTime;
}
public short getUserNameSize() {
return userNameSize;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/SubBlockHeader.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 21.11.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.rarfile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.junrar.io.Raw;
public class SubBlockHeader
extends BlockHeader
{
private Log logger = LogFactory.getLog(getClass());
public static final short SubBlockHeaderSize = 3;
private short subType;
private byte level;
public SubBlockHeader(SubBlockHeader sb)
{
super(sb);
subType = sb.getSubType().getSubblocktype();
level = sb.getLevel();
}
public SubBlockHeader(BlockHeader bh, byte[] subblock)
{
super(bh);
int position = 0;
subType = Raw.readShortLittleEndian(subblock, position);
position +=2;
level |= subblock[position]&0xff;
}
/**
* @return
*/
public byte getLevel() {
return level;
}
/**
* @return
*/
public SubBlockHeaderType getSubType() {
return SubBlockHeaderType.findSubblockHeaderType(subType);
}
public void print()
{
super.print();
logger.info("subtype: "+getSubType());
logger.info("level: "+level);
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/SubBlockHeaderType.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 20.11.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.rarfile;
public enum SubBlockHeaderType
{
EA_HEAD ((short)0x100),
UO_HEAD ((short)0x101),
MAC_HEAD ((short)0x102),
BEEA_HEAD ((short)0x103),
NTACL_HEAD ((short)0x104),
STREAM_HEAD ((short)0x105);
private short subblocktype;
private SubBlockHeaderType(short subblocktype)
{
this.subblocktype = subblocktype;
}
/**
* Return true if the given value is equal to the enum's value
* @param subblocktype
* @return true if the given value is equal to the enum's value
*/
public boolean equals(short subblocktype)
{
return this.subblocktype == subblocktype;
}
/**
* find the header type for the given short value
* @param SubType the short value
* @return the correspo nding enum or null
*/
public static SubBlockHeaderType findSubblockHeaderType(short subType)
{
if(EA_HEAD.equals(subType)){
return EA_HEAD;
}else if(UO_HEAD.equals(subType)){
return UO_HEAD;
}else if(MAC_HEAD.equals(subType)){
return MAC_HEAD;
}else if(BEEA_HEAD.equals(subType)){
return BEEA_HEAD;
}else if(NTACL_HEAD.equals(subType)){
return NTACL_HEAD;
}else if(STREAM_HEAD.equals(subType)){
return STREAM_HEAD;
}
return null;
}
/**
* @return the short representation of this enum
*/
public short getSubblocktype() {
return subblocktype;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/rarfile/UnixOwnersHeader.java
================================================
package com.github.junrar.rarfile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.github.junrar.io.Raw;
public class UnixOwnersHeader
extends SubBlockHeader
{
private Log logger = LogFactory.getLog(UnixOwnersHeader.class);
private int ownerNameSize;
private int groupNameSize;
private String owner;
private String group;
public UnixOwnersHeader(SubBlockHeader sb, byte[] uoHeader) {
super(sb);
int pos = 0;
ownerNameSize = Raw.readShortLittleEndian(uoHeader, pos)&0xFFFF;
pos+=2;
groupNameSize = Raw.readShortLittleEndian(uoHeader, pos)&0xFFFF;
pos+=2;
if(pos+ownerNameSize": ">" or ">"
* "@": "@"
*/
package com.github.junrar.rarfile;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public enum UnrarHeadertype {
/**
*
*/
MainHeader ((byte)0x73),
/**
*
*/
MarkHeader ((byte)0x72),
/**
*
*/
FileHeader ((byte) 0x74),
/**
*
*/
CommHeader ((byte) 0x75),
/**
*
*/
AvHeader ((byte) 0x76),
/**
*
*/
SubHeader ((byte) 0x77),
/**
*
*/
ProtectHeader ((byte) 0x78),
/**
*
*/
SignHeader ((byte) 0x79),
/**
*
*/
NewSubHeader ((byte) 0x7a),
/**
*
*/
EndArcHeader ((byte) 0x7b);
/**
* Returns the enum according to the given byte or null
* @param headerType the headerbyte
* @return the enum or null
*/
public static UnrarHeadertype findType(byte headerType)
{
if(UnrarHeadertype.MarkHeader.equals(headerType)){
return UnrarHeadertype.MarkHeader;
}
if(UnrarHeadertype.MainHeader.equals(headerType)){
return UnrarHeadertype.MainHeader;
}
if(UnrarHeadertype.FileHeader.equals(headerType)){
return UnrarHeadertype.FileHeader;
}
if(UnrarHeadertype.EndArcHeader.equals(headerType)){
return UnrarHeadertype.EndArcHeader;
}
if(UnrarHeadertype.NewSubHeader.equals(headerType)){
return UnrarHeadertype.NewSubHeader;
}
if(UnrarHeadertype.SubHeader.equals(headerType)){
return UnrarHeadertype.SubHeader;
}
if(UnrarHeadertype.SignHeader.equals(headerType)){
return UnrarHeadertype.SignHeader;
}
if(UnrarHeadertype.ProtectHeader.equals(headerType)){
return UnrarHeadertype.ProtectHeader;
}
if(UnrarHeadertype.MarkHeader.equals(headerType)){
return UnrarHeadertype.MarkHeader;
}
if(UnrarHeadertype.MainHeader.equals(headerType)){
return UnrarHeadertype.MainHeader;
}
if(UnrarHeadertype.FileHeader.equals(headerType)){
return UnrarHeadertype.FileHeader;
}
if(UnrarHeadertype.EndArcHeader.equals(headerType)){
return UnrarHeadertype.EndArcHeader;
}
if(UnrarHeadertype.CommHeader.equals(headerType)){
return UnrarHeadertype.CommHeader;
}
if(UnrarHeadertype.AvHeader.equals(headerType)){
return UnrarHeadertype.AvHeader;
}
return null;
}
private byte headerByte;
private UnrarHeadertype(byte headerByte)
{
this.headerByte = headerByte;
}
/**
* Return true if the given byte is equal to the enum's byte
* @param header
* @return true if the given byte is equal to the enum's byte
*/
public boolean equals(byte header)
{
return headerByte == header;
}
/**
* the header byte of this enum
* @return the header byte of this enum
*/
public byte getHeaderByte() {
return headerByte;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ComprDataIO.java
================================================
/*
* 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()
// {
//
// }
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/Unpack.java
================================================
/*
* 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.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import com.github.junrar.exception.RarException;
import com.github.junrar.unpack.decode.Compress;
import com.github.junrar.unpack.ppm.BlockTypes;
import com.github.junrar.unpack.ppm.ModelPPM;
import com.github.junrar.unpack.ppm.SubAllocator;
import com.github.junrar.unpack.vm.BitInput;
import com.github.junrar.unpack.vm.RarVM;
import com.github.junrar.unpack.vm.VMPreparedProgram;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public final class Unpack extends Unpack20 {
private final ModelPPM ppm = new ModelPPM();
private int ppmEscChar;
private RarVM rarVM = new RarVM();
/* Filters code, one entry per filter */
private List filters = new ArrayList();
/* Filters stack, several entrances of same filter are possible */
private List prgStack = new ArrayList();
/*
* lengths of preceding blocks, one length per filter. Used to reduce size
* required to write block length if lengths are repeating
*/
private List oldFilterLengths = new ArrayList();
private int lastFilter;
private boolean tablesRead;
private byte[] unpOldTable = new byte[Compress.HUFF_TABLE_SIZE];
private BlockTypes unpBlockType;
private boolean externalWindow;
private long writtenFileSize;
private boolean fileExtracted;
private boolean ppmError;
private int prevLowDist;
private int lowDistRepCount;
public static int[] DBitLengthCounts = { 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 14, 0, 12 };
public Unpack(ComprDataIO DataIO) {
unpIO = DataIO;
window = null;
externalWindow = false;
suspended = false;
unpAllBuf = false;
unpSomeRead = false;
}
public void init(byte[] window) {
if (window == null) {
this.window = new byte[Compress.MAXWINSIZE];
} else {
this.window = window;
externalWindow = true;
}
inAddr = 0;
unpInitData(false);
}
public void doUnpack(int method, boolean solid) throws IOException,
RarException {
if (unpIO.getSubHeader().getUnpMethod() == 0x30) {
unstoreFile();
}
switch (method) {
case 15: // rar 1.5 compression
unpack15(solid);
break;
case 20: // rar 2.x compression
case 26: // files larger than 2GB
unpack20(solid);
break;
case 29: // rar 3.x compression
case 36: // alternative hash
unpack29(solid);
break;
}
}
private void unstoreFile() throws IOException, RarException {
byte[] buffer = new byte[0x10000];
while (true) {
int code = unpIO.unpRead(buffer, 0, (int) Math.min(buffer.length,
destUnpSize));
if (code == 0 || code == -1)
break;
code = code < destUnpSize ? code : (int) destUnpSize;
unpIO.unpWrite(buffer, 0, code);
if (destUnpSize >= 0)
destUnpSize -= code;
}
}
private void unpack29(boolean solid) throws IOException, RarException {
int[] DDecode = new int[Compress.DC];
byte[] DBits = new byte[Compress.DC];
int Bits;
if (DDecode[1] == 0) {
int Dist = 0, BitLength = 0, Slot = 0;
for (int I = 0; I < DBitLengthCounts.length; I++, BitLength++) {
int count = DBitLengthCounts[I];
for (int J = 0; J < count; J++, Slot++, Dist += (1 << BitLength)) {
DDecode[Slot] = Dist;
DBits[Slot] = (byte) BitLength;
}
}
}
fileExtracted = true;
if (!suspended) {
unpInitData(solid);
if (!unpReadBuf()) {
return;
}
if ((!solid || !tablesRead) && !readTables()) {
return;
}
}
if (ppmError) {
return;
}
while (true) {
unpPtr &= Compress.MAXWINMASK;
if (inAddr > readBorder) {
if (!unpReadBuf()) {
break;
}
}
// System.out.println(((wrPtr - unpPtr) &
// Compress.MAXWINMASK)+":"+wrPtr+":"+unpPtr);
if (((wrPtr - unpPtr) & Compress.MAXWINMASK) < 260
&& wrPtr != unpPtr) {
UnpWriteBuf();
if (writtenFileSize > destUnpSize) {
return;
}
if (suspended) {
fileExtracted = false;
return;
}
}
if (unpBlockType == BlockTypes.BLOCK_PPM) {
int Ch = ppm.decodeChar();
if (Ch == -1) {
ppmError = true;
break;
}
if (Ch == ppmEscChar) {
int NextCh = ppm.decodeChar();
if (NextCh == 0) {
if (!readTables()) {
break;
}
continue;
}
if (NextCh == 2 || NextCh == -1) {
break;
}
if (NextCh == 3) {
if (!readVMCodePPM()) {
break;
}
continue;
}
if (NextCh == 4) {
int Distance = 0, Length = 0;
boolean failed = false;
for (int I = 0; I < 4 && !failed; I++) {
int ch = ppm.decodeChar();
if (ch == -1) {
failed = true;
} else {
if (I == 3) {
// Bug fixed
Length = ch & 0xff;
} else {
// Bug fixed
Distance = (Distance << 8) + (ch & 0xff);
}
}
}
if (failed) {
break;
}
copyString(Length + 32, Distance + 2);
continue;
}
if (NextCh == 5) {
int Length = ppm.decodeChar();
if (Length == -1) {
break;
}
copyString(Length + 4, 1);
continue;
}
}
window[unpPtr++] = (byte) Ch;
continue;
}
int Number = decodeNumber(LD);
if (Number < 256) {
window[unpPtr++] = (byte) Number;
continue;
}
if (Number >= 271) {
int Length = LDecode[Number -= 271] + 3;
if ((Bits = LBits[Number]) > 0) {
Length += getbits() >>> (16 - Bits);
addbits(Bits);
}
int DistNumber = decodeNumber(DD);
int Distance = DDecode[DistNumber] + 1;
if ((Bits = DBits[DistNumber]) > 0) {
if (DistNumber > 9) {
if (Bits > 4) {
Distance += ((getbits() >>> (20 - Bits)) << 4);
addbits(Bits - 4);
}
if (lowDistRepCount > 0) {
lowDistRepCount--;
Distance += prevLowDist;
} else {
int LowDist = decodeNumber(LDD);
if (LowDist == 16) {
lowDistRepCount = Compress.LOW_DIST_REP_COUNT - 1;
Distance += prevLowDist;
} else {
Distance += LowDist;
prevLowDist = LowDist;
}
}
} else {
Distance += getbits() >>> (16 - Bits);
addbits(Bits);
}
}
if (Distance >= 0x2000) {
Length++;
if (Distance >= 0x40000L) {
Length++;
}
}
insertOldDist(Distance);
insertLastMatch(Length, Distance);
copyString(Length, Distance);
continue;
}
if (Number == 256) {
if (!readEndOfBlock()) {
break;
}
continue;
}
if (Number == 257) {
if (!readVMCode()) {
break;
}
continue;
}
if (Number == 258) {
if (lastLength != 0) {
copyString(lastLength, lastDist);
}
continue;
}
if (Number < 263) {
int DistNum = Number - 259;
int Distance = oldDist[DistNum];
for (int I = DistNum; I > 0; I--) {
oldDist[I] = oldDist[I - 1];
}
oldDist[0] = Distance;
int LengthNumber = decodeNumber(RD);
int Length = LDecode[LengthNumber] + 2;
if ((Bits = LBits[LengthNumber]) > 0) {
Length += getbits() >>> (16 - Bits);
addbits(Bits);
}
insertLastMatch(Length, Distance);
copyString(Length, Distance);
continue;
}
if (Number < 272) {
int Distance = SDDecode[Number -= 263] + 1;
if ((Bits = SDBits[Number]) > 0) {
Distance += getbits() >>> (16 - Bits);
addbits(Bits);
}
insertOldDist(Distance);
insertLastMatch(2, Distance);
copyString(2, Distance);
continue;
}
}
UnpWriteBuf();
}
private void UnpWriteBuf() throws IOException {
int WrittenBorder = wrPtr;
int WriteSize = (unpPtr - WrittenBorder) & Compress.MAXWINMASK;
for (int I = 0; I < prgStack.size(); I++) {
UnpackFilter flt = prgStack.get(I);
if (flt == null) {
continue;
}
if (flt.isNextWindow()) {
flt.setNextWindow(false);// ->NextWindow=false;
continue;
}
int BlockStart = flt.getBlockStart();// ->BlockStart;
int BlockLength = flt.getBlockLength();// ->BlockLength;
if (((BlockStart - WrittenBorder) & Compress.MAXWINMASK) < WriteSize) {
if (WrittenBorder != BlockStart) {
UnpWriteArea(WrittenBorder, BlockStart);
WrittenBorder = BlockStart;
WriteSize = (unpPtr - WrittenBorder) & Compress.MAXWINMASK;
}
if (BlockLength <= WriteSize) {
int BlockEnd = (BlockStart + BlockLength)
& Compress.MAXWINMASK;
if (BlockStart < BlockEnd || BlockEnd == 0) {
// VM.SetMemory(0,Window+BlockStart,BlockLength);
rarVM.setMemory(0, window, BlockStart, BlockLength);
} else {
int FirstPartLength = Compress.MAXWINSIZE - BlockStart;
// VM.SetMemory(0,Window+BlockStart,FirstPartLength);
rarVM.setMemory(0, window, BlockStart, FirstPartLength);
// VM.SetMemory(FirstPartLength,Window,BlockEnd);
rarVM.setMemory(FirstPartLength, window, 0, BlockEnd);
}
VMPreparedProgram ParentPrg = filters.get(
flt.getParentFilter()).getPrg();
VMPreparedProgram Prg = flt.getPrg();
if (ParentPrg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) {
// copy global data from previous script execution if
// any
// Prg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
// memcpy(&Prg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
Prg.getGlobalData().setSize(
ParentPrg.getGlobalData().size());
for (int i = 0; i < ParentPrg.getGlobalData().size()
- RarVM.VM_FIXEDGLOBALSIZE; i++) {
Prg.getGlobalData().set(
RarVM.VM_FIXEDGLOBALSIZE + i,
ParentPrg.getGlobalData().get(
RarVM.VM_FIXEDGLOBALSIZE + i));
}
}
ExecuteCode(Prg);
if (Prg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) {
// save global data for next script execution
if (ParentPrg.getGlobalData().size() < Prg
.getGlobalData().size()) {
ParentPrg.getGlobalData().setSize(
Prg.getGlobalData().size());// ->GlobalData.Alloc(Prg->GlobalData.Size());
}
// memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&Prg->GlobalData[VM_FIXEDGLOBALSIZE],Prg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
for (int i = 0; i < Prg.getGlobalData().size()
- RarVM.VM_FIXEDGLOBALSIZE; i++) {
ParentPrg.getGlobalData().set(
RarVM.VM_FIXEDGLOBALSIZE + i,
Prg.getGlobalData().get(
RarVM.VM_FIXEDGLOBALSIZE + i));
}
} else {
ParentPrg.getGlobalData().clear();
}
int FilteredDataOffset = Prg.getFilteredDataOffset();
int FilteredDataSize = Prg.getFilteredDataSize();
byte[] FilteredData = new byte[FilteredDataSize];
for (int i = 0; i < FilteredDataSize; i++) {
FilteredData[i] = rarVM.getMem()[FilteredDataOffset + i];// Prg.getGlobalData().get(FilteredDataOffset
// +
// i);
}
prgStack.set(I, null);
while (I + 1 < prgStack.size()) {
UnpackFilter NextFilter = prgStack.get(I + 1);
if (NextFilter == null
|| NextFilter.getBlockStart() != BlockStart
|| NextFilter.getBlockLength() != FilteredDataSize
|| NextFilter.isNextWindow()) {
break;
}
// apply several filters to same data block
rarVM.setMemory(0, FilteredData, 0, FilteredDataSize);// .SetMemory(0,FilteredData,FilteredDataSize);
VMPreparedProgram pPrg = filters.get(
NextFilter.getParentFilter()).getPrg();
VMPreparedProgram NextPrg = NextFilter.getPrg();
if (pPrg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) {
// copy global data from previous script execution
// if any
// NextPrg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
NextPrg.getGlobalData().setSize(
pPrg.getGlobalData().size());
// memcpy(&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
for (int i = 0; i < pPrg.getGlobalData().size()
- RarVM.VM_FIXEDGLOBALSIZE; i++) {
NextPrg.getGlobalData().set(
RarVM.VM_FIXEDGLOBALSIZE + i,
pPrg.getGlobalData().get(
RarVM.VM_FIXEDGLOBALSIZE + i));
}
}
ExecuteCode(NextPrg);
if (NextPrg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) {
// save global data for next script execution
if (pPrg.getGlobalData().size() < NextPrg
.getGlobalData().size()) {
pPrg.getGlobalData().setSize(
NextPrg.getGlobalData().size());
}
// memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],NextPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
for (int i = 0; i < NextPrg.getGlobalData().size()
- RarVM.VM_FIXEDGLOBALSIZE; i++) {
pPrg.getGlobalData().set(
RarVM.VM_FIXEDGLOBALSIZE + i,
NextPrg.getGlobalData().get(
RarVM.VM_FIXEDGLOBALSIZE + i));
}
} else {
pPrg.getGlobalData().clear();
}
FilteredDataOffset = NextPrg.getFilteredDataOffset();
FilteredDataSize = NextPrg.getFilteredDataSize();
FilteredData = new byte[FilteredDataSize];
for (int i = 0; i < FilteredDataSize; i++) {
FilteredData[i] = NextPrg.getGlobalData().get(
FilteredDataOffset + i);
}
I++;
prgStack.set(I, null);
}
unpIO.unpWrite(FilteredData, 0, FilteredDataSize);
unpSomeRead = true;
writtenFileSize += FilteredDataSize;
WrittenBorder = BlockEnd;
WriteSize = (unpPtr - WrittenBorder) & Compress.MAXWINMASK;
} else {
for (int J = I; J < prgStack.size(); J++) {
UnpackFilter filt = prgStack.get(J);
if (filt != null && filt.isNextWindow()) {
filt.setNextWindow(false);
}
}
wrPtr = WrittenBorder;
return;
}
}
}
UnpWriteArea(WrittenBorder, unpPtr);
wrPtr = unpPtr;
}
private void UnpWriteArea(int startPtr, int endPtr) throws IOException {
if (endPtr != startPtr) {
unpSomeRead = true;
}
if (endPtr < startPtr) {
UnpWriteData(window, startPtr, -startPtr & Compress.MAXWINMASK);
UnpWriteData(window, 0, endPtr);
unpAllBuf = true;
} else {
UnpWriteData(window, startPtr, endPtr - startPtr);
}
}
private void UnpWriteData(byte[] data, int offset, int size)
throws IOException {
if (writtenFileSize >= destUnpSize) {
return;
}
int writeSize = size;
long leftToWrite = destUnpSize - writtenFileSize;
if (writeSize > leftToWrite) {
writeSize = (int) leftToWrite;
}
unpIO.unpWrite(data, offset, writeSize);
writtenFileSize += size;
}
private void insertOldDist(int distance) {
oldDist[3] = oldDist[2];
oldDist[2] = oldDist[1];
oldDist[1] = oldDist[0];
oldDist[0] = distance;
}
private void insertLastMatch(int length, int distance) {
lastDist = distance;
lastLength = length;
}
private void copyString(int length, int distance) {
// System.out.println("copyString(" + length + ", " + distance + ")");
int destPtr = unpPtr - distance;
// System.out.println(unpPtr+":"+distance);
if (destPtr >= 0 && destPtr < Compress.MAXWINSIZE - 260
&& unpPtr < Compress.MAXWINSIZE - 260) {
window[unpPtr++] = window[destPtr++];
while (--length > 0)
window[unpPtr++] = window[destPtr++];
} else
while (length-- != 0) {
window[unpPtr] = window[destPtr++ & Compress.MAXWINMASK];
unpPtr = (unpPtr + 1) & Compress.MAXWINMASK;
}
}
protected void unpInitData(boolean solid) {
if (!solid) {
tablesRead = false;
Arrays.fill(oldDist, 0); // memset(oldDist,0,sizeof(OldDist));
oldDistPtr = 0;
lastDist = 0;
lastLength = 0;
Arrays.fill(unpOldTable, (byte) 0);// memset(UnpOldTable,0,sizeof(UnpOldTable));
unpPtr = 0;
wrPtr = 0;
ppmEscChar = 2;
initFilters();
}
InitBitInput();
ppmError = false;
writtenFileSize = 0;
readTop = 0;
readBorder = 0;
unpInitData20(solid);
}
private void initFilters() {
oldFilterLengths.clear();
lastFilter = 0;
filters.clear();
prgStack.clear();
}
private boolean readEndOfBlock() throws IOException, RarException {
int BitField = getbits();
boolean NewTable, NewFile = false;
if ((BitField & 0x8000) != 0) {
NewTable = true;
addbits(1);
} else {
NewFile = true;
NewTable = (BitField & 0x4000) != 0 ? true : false;
addbits(2);
}
tablesRead = !NewTable;
return !(NewFile || NewTable && !readTables());
}
private boolean readTables() throws IOException, RarException {
byte[] bitLength = new byte[Compress.BC];
byte[] table = new byte[Compress.HUFF_TABLE_SIZE];
if (inAddr > readTop - 25) {
if (!unpReadBuf()) {
return (false);
}
}
faddbits((8 - inBit) & 7);
long bitField = fgetbits() & 0xffFFffFF;
if ((bitField & 0x8000) != 0) {
unpBlockType = BlockTypes.BLOCK_PPM;
return (ppm.decodeInit(this, ppmEscChar));
}
unpBlockType = BlockTypes.BLOCK_LZ;
prevLowDist = 0;
lowDistRepCount = 0;
if ((bitField & 0x4000) == 0) {
Arrays.fill(unpOldTable, (byte) 0);// memset(UnpOldTable,0,sizeof(UnpOldTable));
}
faddbits(2);
for (int i = 0; i < Compress.BC; i++) {
int length = (fgetbits() >>> 12) & 0xFF;
faddbits(4);
if (length == 15) {
int zeroCount = (fgetbits() >>> 12) & 0xFF;
faddbits(4);
if (zeroCount == 0) {
bitLength[i] = 15;
} else {
zeroCount += 2;
while (zeroCount-- > 0 && i < bitLength.length) {
bitLength[i++] = 0;
}
i--;
}
} else {
bitLength[i] = (byte) length;
}
}
makeDecodeTables(bitLength, 0, BD, Compress.BC);
int TableSize = Compress.HUFF_TABLE_SIZE;
for (int i = 0; i < TableSize;) {
if (inAddr > readTop - 5) {
if (!unpReadBuf()) {
return (false);
}
}
int Number = decodeNumber(BD);
if (Number < 16) {
table[i] = (byte) ((Number + unpOldTable[i]) & 0xf);
i++;
} else if (Number < 18) {
int N;
if (Number == 16) {
N = (fgetbits() >>> 13) + 3;
faddbits(3);
} else {
N = (fgetbits() >>> 9) + 11;
faddbits(7);
}
while (N-- > 0 && i < TableSize) {
table[i] = table[i - 1];
i++;
}
} else {
int N;
if (Number == 18) {
N = (fgetbits() >>> 13) + 3;
faddbits(3);
} else {
N = (fgetbits() >>> 9) + 11;
faddbits(7);
}
while (N-- > 0 && i < TableSize) {
table[i++] = 0;
}
}
}
tablesRead = true;
if (inAddr > readTop) {
return (false);
}
makeDecodeTables(table, 0, LD, Compress.NC);
makeDecodeTables(table, Compress.NC, DD, Compress.DC);
makeDecodeTables(table, Compress.NC + Compress.DC, LDD, Compress.LDC);
makeDecodeTables(table, Compress.NC + Compress.DC + Compress.LDC, RD,
Compress.RC);
// memcpy(unpOldTable,table,sizeof(unpOldTable));
for (int i = 0; i < unpOldTable.length; i++) {
unpOldTable[i] = table[i];
}
return (true);
}
private boolean readVMCode() throws IOException, RarException {
int FirstByte = getbits() >> 8;
addbits(8);
int Length = (FirstByte & 7) + 1;
if (Length == 7) {
Length = (getbits() >> 8) + 7;
addbits(8);
} else if (Length == 8) {
Length = getbits();
addbits(16);
}
List vmCode = new ArrayList();
for (int I = 0; I < Length; I++) {
if (inAddr >= readTop - 1 && !unpReadBuf() && I < Length - 1) {
return (false);
}
vmCode.add(Byte.valueOf((byte) (getbits() >> 8)));
addbits(8);
}
return (addVMCode(FirstByte, vmCode, Length));
}
private boolean readVMCodePPM() throws IOException, RarException {
int FirstByte = ppm.decodeChar();
if ((int) FirstByte == -1) {
return (false);
}
int Length = (FirstByte & 7) + 1;
if (Length == 7) {
int B1 = ppm.decodeChar();
if (B1 == -1) {
return (false);
}
Length = B1 + 7;
} else if (Length == 8) {
int B1 = ppm.decodeChar();
if (B1 == -1) {
return (false);
}
int B2 = ppm.decodeChar();
if (B2 == -1) {
return (false);
}
Length = B1 * 256 + B2;
}
List vmCode = new ArrayList();
for (int I = 0; I < Length; I++) {
int Ch = ppm.decodeChar();
if (Ch == -1) {
return (false);
}
vmCode.add(Byte.valueOf((byte) Ch));// VMCode[I]=Ch;
}
return (addVMCode(FirstByte, vmCode, Length));
}
private boolean addVMCode(int firstByte, List vmCode, int length) {
BitInput Inp = new BitInput();
Inp.InitBitInput();
// memcpy(Inp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize));
for (int i = 0; i < Math.min(BitInput.MAX_SIZE, vmCode.size()); i++) {
Inp.getInBuf()[i] = vmCode.get(i);
}
rarVM.init();
int FiltPos;
if ((firstByte & 0x80) != 0) {
FiltPos = RarVM.ReadData(Inp);
if (FiltPos == 0) {
initFilters();
} else {
FiltPos--;
}
} else
FiltPos = lastFilter; // use the same filter as last time
if (FiltPos > filters.size() || FiltPos > oldFilterLengths.size()) {
return (false);
}
lastFilter = FiltPos;
boolean NewFilter = (FiltPos == filters.size());
UnpackFilter StackFilter = new UnpackFilter(); // new filter for
// PrgStack
UnpackFilter Filter;
if (NewFilter) // new filter code, never used before since VM reset
{
// too many different filters, corrupt archive
if (FiltPos > 1024) {
return (false);
}
// Filters[Filters.Size()-1]=Filter=new UnpackFilter;
Filter = new UnpackFilter();
filters.add(Filter);
StackFilter.setParentFilter(filters.size() - 1);
oldFilterLengths.add(0);
Filter.setExecCount(0);
} else // filter was used in the past
{
Filter = filters.get(FiltPos);
StackFilter.setParentFilter(FiltPos);
Filter.setExecCount(Filter.getExecCount() + 1);// ->ExecCount++;
}
prgStack.add(StackFilter);
StackFilter.setExecCount(Filter.getExecCount());// ->ExecCount;
int BlockStart = RarVM.ReadData(Inp);
if ((firstByte & 0x40) != 0) {
BlockStart += 258;
}
StackFilter.setBlockStart((BlockStart + unpPtr) & Compress.MAXWINMASK);
if ((firstByte & 0x20) != 0) {
StackFilter.setBlockLength(RarVM.ReadData(Inp));
} else {
StackFilter
.setBlockLength(FiltPos < oldFilterLengths.size() ? oldFilterLengths
.get(FiltPos)
: 0);
}
StackFilter.setNextWindow((wrPtr != unpPtr)
&& ((wrPtr - unpPtr) & Compress.MAXWINMASK) <= BlockStart);
// DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x
// BlockStart=%08x",UnpPtr,WrPtr,BlockStart);
oldFilterLengths.set(FiltPos, StackFilter.getBlockLength());
// memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR));
Arrays.fill(StackFilter.getPrg().getInitR(), 0);
StackFilter.getPrg().getInitR()[3] = RarVM.VM_GLOBALMEMADDR;// StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR;
StackFilter.getPrg().getInitR()[4] = StackFilter.getBlockLength();// StackFilter->Prg.InitR[4]=StackFilter->BlockLength;
StackFilter.getPrg().getInitR()[5] = StackFilter.getExecCount();// StackFilter->Prg.InitR[5]=StackFilter->ExecCount;
if ((firstByte & 0x10) != 0) // set registers to optional parameters
// if any
{
int InitMask = Inp.fgetbits() >>> 9;
Inp.faddbits(7);
for (int I = 0; I < 7; I++) {
if ((InitMask & (1 << I)) != 0) {
// StackFilter->Prg.InitR[I]=RarVM::ReadData(Inp);
StackFilter.getPrg().getInitR()[I] = RarVM.ReadData(Inp);
}
}
}
if (NewFilter) {
int VMCodeSize = RarVM.ReadData(Inp);
if (VMCodeSize >= 0x10000 || VMCodeSize == 0) {
return (false);
}
byte[] VMCode = new byte[VMCodeSize];
for (int I = 0; I < VMCodeSize; I++) {
if (Inp.Overflow(3)) {
return (false);
}
VMCode[I] = (byte) (Inp.fgetbits() >> 8);
Inp.faddbits(8);
}
// VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg);
rarVM.prepare(VMCode, VMCodeSize, Filter.getPrg());
}
StackFilter.getPrg().setAltCmd(Filter.getPrg().getCmd());// StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0];
StackFilter.getPrg().setCmdCount(Filter.getPrg().getCmdCount());// StackFilter->Prg.CmdCount=Filter->Prg.CmdCount;
int StaticDataSize = Filter.getPrg().getStaticData().size();
if (StaticDataSize > 0 && StaticDataSize < RarVM.VM_GLOBALMEMSIZE) {
// read statically defined data contained in DB commands
// StackFilter->Prg.StaticData.Add(StaticDataSize);
StackFilter.getPrg().setStaticData(Filter.getPrg().getStaticData());
// memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize);
}
if (StackFilter.getPrg().getGlobalData().size() < RarVM.VM_FIXEDGLOBALSIZE) {
// StackFilter->Prg.GlobalData.Reset();
// StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE);
StackFilter.getPrg().getGlobalData().clear();
StackFilter.getPrg().getGlobalData().setSize(
RarVM.VM_FIXEDGLOBALSIZE);
}
// byte *GlobalData=&StackFilter->Prg.GlobalData[0];
Vector globalData = StackFilter.getPrg().getGlobalData();
for (int I = 0; I < 7; I++) {
rarVM.setLowEndianValue(globalData, I * 4, StackFilter.getPrg()
.getInitR()[I]);
}
// VM.SetLowEndianValue((uint
// *)&GlobalData[0x1c],StackFilter->BlockLength);
rarVM.setLowEndianValue(globalData, 0x1c, StackFilter.getBlockLength());
// VM.SetLowEndianValue((uint *)&GlobalData[0x20],0);
rarVM.setLowEndianValue(globalData, 0x20, 0);
rarVM.setLowEndianValue(globalData, 0x24, 0);
rarVM.setLowEndianValue(globalData, 0x28, 0);
// VM.SetLowEndianValue((uint
// *)&GlobalData[0x2c],StackFilter->ExecCount);
rarVM.setLowEndianValue(globalData, 0x2c, StackFilter.getExecCount());
// memset(&GlobalData[0x30],0,16);
for (int i = 0; i < 16; i++) {
globalData.set(0x30 + i, Byte.valueOf((byte) (0)));
}
if ((firstByte & 8) != 0) // put data block passed as parameter if any
{
if (Inp.Overflow(3)) {
return (false);
}
int DataSize = RarVM.ReadData(Inp);
if (DataSize > RarVM.VM_GLOBALMEMSIZE - RarVM.VM_FIXEDGLOBALSIZE) {
return (false);
}
int CurSize = StackFilter.getPrg().getGlobalData().size();
if (CurSize < DataSize + RarVM.VM_FIXEDGLOBALSIZE) {
// StackFilter->Prg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize);
StackFilter.getPrg().getGlobalData().setSize(
DataSize + RarVM.VM_FIXEDGLOBALSIZE - CurSize);
}
int offset = RarVM.VM_FIXEDGLOBALSIZE;
globalData = StackFilter.getPrg().getGlobalData();
for (int I = 0; I < DataSize; I++) {
if (Inp.Overflow(3)) {
return (false);
}
globalData.set(offset + I, Byte
.valueOf((byte) (Inp.fgetbits() >>> 8)));
Inp.faddbits(8);
}
}
return (true);
}
private void ExecuteCode(VMPreparedProgram Prg) {
if (Prg.getGlobalData().size() > 0) {
// Prg->InitR[6]=int64to32(WrittenFileSize);
Prg.getInitR()[6] = (int) (writtenFileSize);
// rarVM.SetLowEndianValue((uint
// *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize));
rarVM.setLowEndianValue(Prg.getGlobalData(), 0x24,
(int) writtenFileSize);
// rarVM.SetLowEndianValue((uint
// *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>32));
rarVM.setLowEndianValue(Prg.getGlobalData(), 0x28,
(int) (writtenFileSize >>> 32));
rarVM.execute(Prg);
}
}
// Duplicate method
// private boolean ReadEndOfBlock() throws IOException, RarException
// {
// int BitField = getbits();
// boolean NewTable, NewFile = false;
// if ((BitField & 0x8000) != 0) {
// NewTable = true;
// addbits(1);
// } else {
// NewFile = true;
// NewTable = (BitField & 0x4000) != 0;
// addbits(2);
// }
// tablesRead = !NewTable;
// return !(NewFile || NewTable && !readTables());
// }
public boolean isFileExtracted() {
return fileExtracted;
}
public void setDestSize(long destSize) {
this.destUnpSize = destSize;
this.fileExtracted = false;
}
public void setSuspended(boolean suspended) {
this.suspended = suspended;
}
public int getChar() throws IOException, RarException {
if (inAddr > BitInput.MAX_SIZE - 30) {
unpReadBuf();
}
return (inBuf[inAddr++] & 0xff);
}
public int getPpmEscChar() {
return ppmEscChar;
}
public void setPpmEscChar(int ppmEscChar) {
this.ppmEscChar = ppmEscChar;
}
public void cleanUp() {
if (ppm != null) {
SubAllocator allocator = ppm.getSubAlloc();
if (allocator != null) {
allocator.stopSubAllocator();
}
}
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/Unpack15.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 21.06.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.IOException;
import java.util.Arrays;
import com.github.junrar.exception.RarException;
import com.github.junrar.unpack.decode.Compress;
import com.github.junrar.unpack.vm.BitInput;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public abstract class Unpack15 extends BitInput
{
protected int readBorder;
protected boolean suspended;
protected boolean unpAllBuf;
protected ComprDataIO unpIO;
protected boolean unpSomeRead;
protected int readTop;
protected long destUnpSize;
protected byte[] window;
protected int[] oldDist = new int[4];
protected int unpPtr, wrPtr;
protected int oldDistPtr;
protected int[] ChSet = new int[256], ChSetA = new int[256],
ChSetB = new int[256], ChSetC = new int[256];
protected int[] Place = new int[256], PlaceA = new int[256],
PlaceB = new int[256], PlaceC = new int[256];
protected int[] NToPl = new int[256], NToPlB = new int[256],
NToPlC = new int[256];
protected int FlagBuf, AvrPlc, AvrPlcB, AvrLn1, AvrLn2, AvrLn3;
protected int Buf60, NumHuf, StMode, LCount, FlagsCnt;
protected int Nhfb, Nlzb, MaxDist3;
protected int lastDist, lastLength;
private static final int STARTL1 = 2;
private static int DecL1[] = { 0x8000, 0xa000, 0xc000, 0xd000, 0xe000,
0xea00, 0xee00, 0xf000, 0xf200, 0xf200, 0xffff };
private static int PosL1[] = { 0, 0, 0, 2, 3, 5, 7, 11, 16, 20, 24, 32, 32 };
private static final int STARTL2 = 3;
private static int DecL2[] = { 0xa000, 0xc000, 0xd000, 0xe000, 0xea00,
0xee00, 0xf000, 0xf200, 0xf240, 0xffff };
private static int PosL2[] = { 0, 0, 0, 0, 5, 7, 9, 13, 18, 22, 26, 34, 36 };
private static final int STARTHF0 = 4;
private static int DecHf0[] = { 0x8000, 0xc000, 0xe000, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xffff };
private static int PosHf0[] = { 0, 0, 0, 0, 0, 8, 16, 24, 33, 33, 33, 33,
33 };
private static final int STARTHF1 = 5;
private static int DecHf1[] = { 0x2000, 0xc000, 0xe000, 0xf000, 0xf200,
0xf200, 0xf7e0, 0xffff };
private static int PosHf1[] = { 0, 0, 0, 0, 0, 0, 4, 44, 60, 76, 80, 80,
127 };
private static final int STARTHF2 = 5;
private static int DecHf2[] = { 0x1000, 0x2400, 0x8000, 0xc000, 0xfa00,
0xffff, 0xffff, 0xffff };
private static int PosHf2[] = { 0, 0, 0, 0, 0, 0, 2, 7, 53, 117, 233, 0, 0 };
private static final int STARTHF3 = 6;
private static int DecHf3[] = { 0x800, 0x2400, 0xee00, 0xfe80, 0xffff,
0xffff, 0xffff };
private static int PosHf3[] = { 0, 0, 0, 0, 0, 0, 0, 2, 16, 218, 251, 0, 0 };
private static final int STARTHF4 = 8;
private static int DecHf4[] = { 0xff00, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff };
private static int PosHf4[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0 };
static int ShortLen1[] = { 1, 3, 4, 4, 5, 6, 7, 8, 8, 4, 4, 5, 6, 6, 4, 0 };
static int ShortXor1[] = { 0, 0xa0, 0xd0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe,
0xff, 0xc0, 0x80, 0x90, 0x98, 0x9c, 0xb0 };
static int ShortLen2[] = { 2, 3, 3, 3, 4, 4, 5, 6, 6, 4, 4, 5, 6, 6, 4, 0 };
static int ShortXor2[] = { 0, 0x40, 0x60, 0xa0, 0xd0, 0xe0, 0xf0, 0xf8,
0xfc, 0xc0, 0x80, 0x90, 0x98, 0x9c, 0xb0 };
protected abstract void unpInitData(boolean solid);
protected void unpack15(boolean solid) throws IOException, RarException
{
if (suspended) {
unpPtr = wrPtr;
} else {
unpInitData(solid);
oldUnpInitData(solid);
unpReadBuf();
if (!solid) {
initHuff();
unpPtr = 0;
} else {
unpPtr = wrPtr;
}
--destUnpSize;
}
if (destUnpSize >= 0) {
getFlagsBuf();
FlagsCnt = 8;
}
while (destUnpSize >= 0) {
unpPtr &= Compress.MAXWINMASK;
if (inAddr > readTop - 30 && !unpReadBuf()) {
break;
}
if (((wrPtr - unpPtr) & Compress.MAXWINMASK) < 270
&& wrPtr != unpPtr) {
oldUnpWriteBuf();
if (suspended) {
return;
}
}
if (StMode != 0) {
huffDecode();
continue;
}
if (--FlagsCnt < 0) {
getFlagsBuf();
FlagsCnt = 7;
}
if ((FlagBuf & 0x80) != 0) {
FlagBuf <<= 1;
if (Nlzb > Nhfb) {
longLZ();
} else {
huffDecode();
}
} else {
FlagBuf <<= 1;
if (--FlagsCnt < 0) {
getFlagsBuf();
FlagsCnt = 7;
}
if ((FlagBuf & 0x80) != 0) {
FlagBuf <<= 1;
if (Nlzb > Nhfb) {
huffDecode();
} else {
longLZ();
}
} else {
FlagBuf <<= 1;
shortLZ();
}
}
}
oldUnpWriteBuf();
}
protected boolean unpReadBuf() throws IOException, RarException
{
int dataSize=readTop-inAddr;
if (dataSize<0){
return(false);
}
if (inAddr>BitInput.MAX_SIZE/2) {
if (dataSize>0){
//memmove(InBuf,InBuf+InAddr,DataSize);
// for (int i = 0; i < dataSize; i++) {
// inBuf[i] = inBuf[inAddr + i];
// }
System.arraycopy(inBuf, inAddr, inBuf, 0, dataSize);
}
inAddr=0;
readTop=dataSize;
}
else{
dataSize=readTop;
}
//int readCode=UnpIO->UnpRead(InBuf+DataSize,(BitInput::MAX_SIZE-DataSize)&~0xf);
int readCode=unpIO.unpRead(inBuf, dataSize, (BitInput.MAX_SIZE-dataSize)&~0xf);
if (readCode>0){
readTop+=readCode;
}
readBorder=readTop-30;
return(readCode!=-1);
}
private int getShortLen1(int pos)
{
return pos == 1 ? Buf60 + 3 : ShortLen1[pos];
}
private int getShortLen2(int pos)
{
return pos == 3 ? Buf60 + 3 : ShortLen2[pos];
}
protected void shortLZ()
{
int Length, SaveLength;
int LastDistance;
int Distance;
int DistancePlace;
NumHuf = 0;
int BitField = fgetbits();
if (LCount == 2) {
faddbits(1);
if (BitField >= 0x8000) {
oldCopyString(lastDist, lastLength);
return;
}
BitField <<= 1;
LCount = 0;
}
BitField >>>= 8;
if (AvrLn1 < 37) {
for (Length = 0;; Length++) {
if (((BitField ^ ShortXor1[Length]) & (~(0xff >>> getShortLen1(Length)))) == 0) {
break;
}
}
faddbits(getShortLen1(Length));
} else {
for (Length = 0;; Length++) {
if (((BitField ^ ShortXor2[Length]) & (~(0xff >> getShortLen2(Length)))) == 0) {
break;
}
}
faddbits(getShortLen2(Length));
}
if (Length >= 9) {
if (Length == 9) {
LCount++;
oldCopyString(lastDist, lastLength);
return;
}
if (Length == 14) {
LCount = 0;
Length = decodeNum(fgetbits(), STARTL2, DecL2, PosL2) + 5;
Distance = (fgetbits() >> 1) | 0x8000;
faddbits(15);
lastLength = Length;
lastDist = Distance;
oldCopyString(Distance, Length);
return;
}
LCount = 0;
SaveLength = Length;
Distance = oldDist[(oldDistPtr - (Length - 9)) & 3];
Length = decodeNum(fgetbits(), STARTL1, DecL1, PosL1) + 2;
if (Length == 0x101 && SaveLength == 10) {
Buf60 ^= 1;
return;
}
if (Distance > 256)
Length++;
if (Distance >= MaxDist3)
Length++;
oldDist[oldDistPtr++] = Distance;
oldDistPtr = oldDistPtr & 3;
lastLength = Length;
lastDist = Distance;
oldCopyString(Distance, Length);
return;
}
LCount = 0;
AvrLn1 += Length;
AvrLn1 -= AvrLn1 >> 4;
DistancePlace = decodeNum(fgetbits(), STARTHF2, DecHf2, PosHf2) & 0xff;
Distance = ChSetA[DistancePlace];
if (--DistancePlace != -1) {
PlaceA[Distance]--;
LastDistance = ChSetA[DistancePlace];
PlaceA[LastDistance]++;
ChSetA[DistancePlace + 1] = LastDistance;
ChSetA[DistancePlace] = Distance;
}
Length += 2;
oldDist[oldDistPtr++] = ++Distance;
oldDistPtr = oldDistPtr & 3;
lastLength = Length;
lastDist = Distance;
oldCopyString(Distance, Length);
}
protected void longLZ()
{
int Length;
int Distance;
int DistancePlace, NewDistancePlace;
int OldAvr2, OldAvr3;
NumHuf = 0;
Nlzb += 16;
if (Nlzb > 0xff) {
Nlzb = 0x90;
Nhfb >>>= 1;
}
OldAvr2 = AvrLn2;
int BitField = fgetbits();
if (AvrLn2 >= 122) {
Length = decodeNum(BitField, STARTL2, DecL2, PosL2);
} else {
if (AvrLn2 >= 64) {
Length = decodeNum(BitField, STARTL1, DecL1, PosL1);
} else {
if (BitField < 0x100) {
Length = BitField;
faddbits(16);
} else {
for (Length = 0; ((BitField << Length) & 0x8000) == 0; Length++) {
;
}
faddbits(Length + 1);
}
}
}
AvrLn2 += Length;
AvrLn2 -= AvrLn2 >>> 5;
BitField = fgetbits();
if (AvrPlcB > 0x28ff) {
DistancePlace = decodeNum(BitField, STARTHF2, DecHf2, PosHf2);
} else {
if (AvrPlcB > 0x6ff) {
DistancePlace = decodeNum(BitField, STARTHF1, DecHf1, PosHf1);
} else {
DistancePlace = decodeNum(BitField, STARTHF0, DecHf0, PosHf0);
}
}
AvrPlcB += DistancePlace;
AvrPlcB -= AvrPlcB >> 8;
while (true) {
Distance = ChSetB[DistancePlace & 0xff];
NewDistancePlace = NToPlB[Distance++ & 0xff]++;
if ((Distance & 0xff) == 0) {
corrHuff(ChSetB, NToPlB);
} else {
break;
}
}
ChSetB[DistancePlace] = ChSetB[NewDistancePlace];
ChSetB[NewDistancePlace] = Distance;
Distance = ((Distance & 0xff00) | (fgetbits() >>> 8)) >>> 1;
faddbits(7);
OldAvr3 = AvrLn3;
if (Length != 1 && Length != 4) {
if (Length == 0 && Distance <= MaxDist3) {
AvrLn3++;
AvrLn3 -= AvrLn3 >> 8;
} else {
if (AvrLn3 > 0) {
AvrLn3--;
}
}
}
Length += 3;
if (Distance >= MaxDist3) {
Length++;
}
if (Distance <= 256) {
Length += 8;
}
if (OldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && OldAvr2 < 0x40) {
MaxDist3 = 0x7f00;
} else {
MaxDist3 = 0x2001;
}
oldDist[oldDistPtr++] = Distance;
oldDistPtr = oldDistPtr & 3;
lastLength = Length;
lastDist = Distance;
oldCopyString(Distance, Length);
}
protected void huffDecode()
{
int CurByte, NewBytePlace;
int Length;
int Distance;
int BytePlace;
int BitField = fgetbits();
if (AvrPlc > 0x75ff) {
BytePlace = decodeNum(BitField, STARTHF4, DecHf4, PosHf4);
} else {
if (AvrPlc > 0x5dff) {
BytePlace = decodeNum(BitField, STARTHF3, DecHf3, PosHf3);
} else {
if (AvrPlc > 0x35ff) {
BytePlace = decodeNum(BitField, STARTHF2, DecHf2, PosHf2);
} else {
if (AvrPlc > 0x0dff) {
BytePlace = decodeNum(BitField, STARTHF1, DecHf1,
PosHf1);
} else {
BytePlace = decodeNum(BitField, STARTHF0, DecHf0,
PosHf0);
}
}
}
}
BytePlace &= 0xff;
if (StMode != 0) {
if (BytePlace == 0 && BitField > 0xfff) {
BytePlace = 0x100;
}
if (--BytePlace == -1) {
BitField = fgetbits();
faddbits(1);
if ((BitField & 0x8000) != 0) {
NumHuf = StMode = 0;
return;
} else {
Length = (BitField & 0x4000) != 0 ? 4 : 3;
faddbits(1);
Distance = decodeNum(fgetbits(), STARTHF2, DecHf2, PosHf2);
Distance = (Distance << 5) | (fgetbits() >>> 11);
faddbits(5);
oldCopyString(Distance, Length);
return;
}
}
} else {
if (NumHuf++ >= 16 && FlagsCnt == 0) {
StMode = 1;
}
}
AvrPlc += BytePlace;
AvrPlc -= AvrPlc >>> 8;
Nhfb += 16;
if (Nhfb > 0xff) {
Nhfb = 0x90;
Nlzb >>>= 1;
}
window[unpPtr++] = (byte) (ChSet[BytePlace] >>> 8);
--destUnpSize;
while (true) {
CurByte = ChSet[BytePlace];
NewBytePlace = NToPl[CurByte++ & 0xff]++;
if ((CurByte & 0xff) > 0xa1) {
corrHuff(ChSet, NToPl);
} else {
break;
}
}
ChSet[BytePlace] = ChSet[NewBytePlace];
ChSet[NewBytePlace] = CurByte;
}
protected void getFlagsBuf()
{
int Flags, NewFlagsPlace;
int FlagsPlace = decodeNum(fgetbits(), STARTHF2, DecHf2, PosHf2);
while (true) {
Flags = ChSetC[FlagsPlace];
FlagBuf = Flags >>> 8;
NewFlagsPlace = NToPlC[Flags++ & 0xff]++;
if ((Flags & 0xff) != 0) {
break;
}
corrHuff(ChSetC, NToPlC);
}
ChSetC[FlagsPlace] = ChSetC[NewFlagsPlace];
ChSetC[NewFlagsPlace] = Flags;
}
protected void oldUnpInitData(boolean Solid)
{
if (!Solid ) {
AvrPlcB = AvrLn1 = AvrLn2 = AvrLn3 = NumHuf = Buf60 = 0;
AvrPlc = 0x3500;
MaxDist3 = 0x2001;
Nhfb = Nlzb = 0x80;
}
FlagsCnt = 0;
FlagBuf = 0;
StMode = 0;
LCount = 0;
readTop = 0;
}
protected void initHuff()
{
for (int I = 0; I < 256; I++) {
Place[I] = PlaceA[I] = PlaceB[I] = I;
PlaceC[I] = (~I + 1) & 0xff;
ChSet[I] = ChSetB[I] = I << 8;
ChSetA[I] = I;
ChSetC[I] = ((~I + 1) & 0xff) << 8;
}
Arrays.fill(NToPl, 0);// memset(NToPl,0,sizeof(NToPl));
Arrays.fill(NToPlB, 0); // memset(NToPlB,0,sizeof(NToPlB));
Arrays.fill(NToPlC, 0); // memset(NToPlC,0,sizeof(NToPlC));
corrHuff(ChSetB, NToPlB);
}
protected void corrHuff(int[] CharSet, int[] NumToPlace)
{
int I, J, pos = 0;
for (I = 7; I >= 0; I--) {
for (J = 0; J < 32; J++, pos++) {
CharSet[pos] = ((CharSet[pos] & ~0xff) | I);// *CharSet=(*CharSet
// & ~0xff) | I;
}
}
Arrays.fill(NumToPlace, 0);// memset(NumToPlace,0,sizeof(NToPl));
for (I = 6; I >= 0; I--) {
NumToPlace[I] = (7 - I) * 32;
}
}
protected void oldCopyString(int Distance, int Length)
{
destUnpSize -= Length;
while ((Length--) != 0) {
window[unpPtr] = window[(unpPtr - Distance) & Compress.MAXWINMASK];
unpPtr = (unpPtr + 1) & Compress.MAXWINMASK;
}
}
protected int decodeNum(int Num, int StartPos, int[] DecTab, int[] PosTab)
{
int I;
for (Num &= 0xfff0, I = 0; DecTab[I] <= Num; I++) {
StartPos++;
}
faddbits(StartPos);
return (((Num - (I != 0 ? DecTab[I - 1] : 0)) >>> (16 - StartPos)) + PosTab[StartPos]);
}
protected void oldUnpWriteBuf() throws IOException
{
if (unpPtr != wrPtr) {
unpSomeRead = true;
}
if (unpPtr < wrPtr) {
unpIO.unpWrite(window, wrPtr, -wrPtr & Compress.MAXWINMASK);
unpIO.unpWrite(window, 0, unpPtr);
unpAllBuf = true;
} else {
unpIO.unpWrite(window, wrPtr, unpPtr - wrPtr);
}
wrPtr = unpPtr;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/Unpack20.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 21.06.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.IOException;
import java.util.Arrays;
import com.github.junrar.exception.RarException;
import com.github.junrar.unpack.decode.AudioVariables;
import com.github.junrar.unpack.decode.BitDecode;
import com.github.junrar.unpack.decode.Compress;
import com.github.junrar.unpack.decode.Decode;
import com.github.junrar.unpack.decode.DistDecode;
import com.github.junrar.unpack.decode.LitDecode;
import com.github.junrar.unpack.decode.LowDistDecode;
import com.github.junrar.unpack.decode.MultDecode;
import com.github.junrar.unpack.decode.RepDecode;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public abstract class Unpack20 extends Unpack15
{
protected MultDecode[] MD = new MultDecode[4];
protected byte[] UnpOldTable20 = new byte[Compress.MC20 * 4];
protected int UnpAudioBlock, UnpChannels, UnpCurChannel, UnpChannelDelta;
protected AudioVariables[] AudV = new AudioVariables[4];
protected LitDecode LD = new LitDecode();
protected DistDecode DD = new DistDecode();
protected LowDistDecode LDD = new LowDistDecode();
protected RepDecode RD = new RepDecode();
protected BitDecode BD = new BitDecode();
public static final int[] LDecode = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12,
14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192,
224 };
public static final byte[] LBits = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2,
2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 };
public static final int[] DDecode = { 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32,
48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072,
4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152, 65536, 98304,
131072, 196608, 262144, 327680, 393216, 458752, 524288, 589824,
655360, 720896, 786432, 851968, 917504, 983040 };
public static final int[] DBits = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5,
5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 };
public static final int[] SDDecode = { 0, 4, 8, 16, 32, 64, 128, 192 };
public static final int[] SDBits = { 2, 2, 3, 4, 5, 6, 6, 6 };
protected void unpack20(boolean solid) throws IOException, RarException
{
int Bits;
if (suspended) {
unpPtr = wrPtr;
} else {
unpInitData(solid);
if (!unpReadBuf()) {
return;
}
if (!solid) {
if (!ReadTables20()) {
return;
}
}
--destUnpSize;
}
while (destUnpSize >= 0) {
unpPtr &= Compress.MAXWINMASK;
if (inAddr > readTop - 30)
if (!unpReadBuf())
break;
if (((wrPtr - unpPtr) & Compress.MAXWINMASK) < 270
&& wrPtr != unpPtr) {
oldUnpWriteBuf();
if (suspended)
return;
}
if (UnpAudioBlock != 0) {
int AudioNumber = decodeNumber(MD[UnpCurChannel]);
if (AudioNumber == 256) {
if (!ReadTables20())
break;
continue;
}
window[unpPtr++] = DecodeAudio(AudioNumber);
if (++UnpCurChannel == UnpChannels)
UnpCurChannel = 0;
--destUnpSize;
continue;
}
int Number = decodeNumber(LD);
if (Number < 256) {
window[unpPtr++] = (byte) Number;
--destUnpSize;
continue;
}
if (Number > 269) {
int Length = LDecode[Number -= 270] + 3;
if ((Bits = LBits[Number]) > 0) {
Length += getbits() >>> (16 - Bits);
addbits(Bits);
}
int DistNumber = decodeNumber(DD);
int Distance = DDecode[DistNumber] + 1;
if ((Bits = DBits[DistNumber]) > 0) {
Distance += getbits() >>> (16 - Bits);
addbits(Bits);
}
if (Distance >= 0x2000) {
Length++;
if (Distance >= 0x40000L)
Length++;
}
CopyString20(Length, Distance);
continue;
}
if (Number == 269) {
if (!ReadTables20())
break;
continue;
}
if (Number == 256) {
CopyString20(lastLength, lastDist);
continue;
}
if (Number < 261) {
int Distance = oldDist[(oldDistPtr - (Number - 256)) & 3];
int LengthNumber = decodeNumber(RD);
int Length = LDecode[LengthNumber] + 2;
if ((Bits = LBits[LengthNumber]) > 0) {
Length += getbits() >>> (16 - Bits);
addbits(Bits);
}
if (Distance >= 0x101) {
Length++;
if (Distance >= 0x2000) {
Length++;
if (Distance >= 0x40000)
Length++;
}
}
CopyString20(Length, Distance);
continue;
}
if (Number < 270) {
int Distance = SDDecode[Number -= 261] + 1;
if ((Bits = SDBits[Number]) > 0) {
Distance += getbits() >>> (16 - Bits);
addbits(Bits);
}
CopyString20(2, Distance);
continue;
}
}
ReadLastTables();
oldUnpWriteBuf();
}
protected void CopyString20(int Length, int Distance)
{
lastDist = oldDist[oldDistPtr++ & 3] = Distance;
lastLength = Length;
destUnpSize -= Length;
int DestPtr = unpPtr - Distance;
if (DestPtr < Compress.MAXWINSIZE - 300
&& unpPtr < Compress.MAXWINSIZE - 300) {
window[unpPtr++] = window[DestPtr++];
window[unpPtr++] = window[DestPtr++];
while (Length > 2) {
Length--;
window[unpPtr++] = window[DestPtr++];
}
} else {
while ((Length--) != 0) {
window[unpPtr] = window[DestPtr++ & Compress.MAXWINMASK];
unpPtr = (unpPtr + 1) & Compress.MAXWINMASK;
}
}
}
protected void makeDecodeTables(byte[] lenTab, int offset, Decode dec,
int size)
{
int[] lenCount = new int[16];
int[] tmpPos = new int[16];
int i;
long M, N;
Arrays.fill(lenCount, 0);// memset(LenCount,0,sizeof(LenCount));
Arrays.fill(dec.getDecodeNum(), 0);// memset(Dec->DecodeNum,0,Size*sizeof(*Dec->DecodeNum));
for (i = 0; i < size; i++) {
lenCount[(int) (lenTab[offset + i] & 0xF)]++;
}
lenCount[0] = 0;
for (tmpPos[0] = 0, dec.getDecodePos()[0] = 0, dec.getDecodeLen()[0] = 0, N = 0, i = 1; i < 16; i++) {
N = 2 * (N + lenCount[i]);
M = N << (15 - i);
if (M > 0xFFFF) {
M = 0xFFFF;
}
dec.getDecodeLen()[i] = (int) M;
tmpPos[i] = dec.getDecodePos()[i] = dec.getDecodePos()[i - 1]
+ lenCount[i - 1];
}
for (i = 0; i < size; i++) {
if (lenTab[offset + i] != 0) {
dec.getDecodeNum()[tmpPos[lenTab[offset + i] & 0xF]++] = i;
}
}
dec.setMaxNum(size);
}
protected int decodeNumber(Decode dec)
{
int bits;
long bitField = getbits() & 0xfffe;
// if (bitField < dec.getDecodeLen()[8]) {
// if (bitField < dec.getDecodeLen()[4]) {
// if (bitField < dec.getDecodeLen()[2]) {
// if (bitField < dec.getDecodeLen()[1]) {
// bits = 1;
// } else {
// bits = 2;
// }
// } else {
// if (bitField < dec.getDecodeLen()[3]) {
// bits = 3;
// } else {
// bits = 4;
// }
// }
// } else {
// if (bitField < dec.getDecodeLen()[6]) {
// if (bitField < dec.getDecodeLen()[5])
// bits = 5;
// else
// bits = 6;
// } else {
// if (bitField < dec.getDecodeLen()[7]) {
// bits = 7;
// } else {
// bits = 8;
// }
// }
// }
// } else {
// if (bitField < dec.getDecodeLen()[12]) {
// if (bitField < dec.getDecodeLen()[10])
// if (bitField < dec.getDecodeLen()[9])
// bits = 9;
// else
// bits = 10;
// else if (bitField < dec.getDecodeLen()[11])
// bits = 11;
// else
// bits = 12;
// } else {
// if (bitField < dec.getDecodeLen()[14]) {
// if (bitField < dec.getDecodeLen()[13]) {
// bits = 13;
// } else {
// bits = 14;
// }
// } else {
// bits = 15;
// }
// }
// }
// addbits(bits);
// int N = dec.getDecodePos()[bits]
// + (((int) bitField - dec.getDecodeLen()[bits - 1]) >>> (16 - bits));
// if (N >= dec.getMaxNum()) {
// N = 0;
// }
// return (dec.getDecodeNum()[N]);
int[] decodeLen = dec.getDecodeLen();
if (bitField < decodeLen[8]) {
if (bitField < decodeLen[4]) {
if (bitField < decodeLen[2]) {
if (bitField < decodeLen[1]) {
bits = 1;
} else {
bits = 2;
}
} else {
if (bitField < decodeLen[3]) {
bits = 3;
} else {
bits = 4;
}
}
} else {
if (bitField < decodeLen[6]) {
if (bitField < decodeLen[5])
bits = 5;
else
bits = 6;
} else {
if (bitField < decodeLen[7]) {
bits = 7;
} else {
bits = 8;
}
}
}
} else {
if (bitField < decodeLen[12]) {
if (bitField < decodeLen[10])
if (bitField < decodeLen[9])
bits = 9;
else
bits = 10;
else if (bitField < decodeLen[11])
bits = 11;
else
bits = 12;
} else {
if (bitField < decodeLen[14]) {
if (bitField < decodeLen[13]) {
bits = 13;
} else {
bits = 14;
}
} else {
bits = 15;
}
}
}
addbits(bits);
int N = dec.getDecodePos()[bits]
+ (((int) bitField - decodeLen[bits - 1]) >>> (16 - bits));
if (N >= dec.getMaxNum()) {
N = 0;
}
return (dec.getDecodeNum()[N]);
}
protected boolean ReadTables20() throws IOException, RarException
{
byte[] BitLength = new byte[Compress.BC20];
byte[] Table = new byte[Compress.MC20 * 4];
int TableSize, N, I;
if (inAddr > readTop - 25) {
if (!unpReadBuf()) {
return (false);
}
}
int BitField = getbits();
UnpAudioBlock = (BitField & 0x8000);
if (0 == (BitField & 0x4000)) {
// memset(UnpOldTable20,0,sizeof(UnpOldTable20));
Arrays.fill(UnpOldTable20, (byte) 0);
}
addbits(2);
if (UnpAudioBlock != 0) {
UnpChannels = ((BitField >>> 12) & 3) + 1;
if (UnpCurChannel >= UnpChannels) {
UnpCurChannel = 0;
}
addbits(2);
TableSize = Compress.MC20 * UnpChannels;
} else {
TableSize = Compress.NC20 + Compress.DC20 + Compress.RC20;
}
for (I = 0; I < Compress.BC20; I++) {
BitLength[I] = (byte) (getbits() >>> 12);
addbits(4);
}
makeDecodeTables(BitLength, 0, BD, Compress.BC20);
I = 0;
while (I < TableSize) {
if (inAddr > readTop - 5) {
if (!unpReadBuf()) {
return (false);
}
}
int Number = decodeNumber(BD);
if (Number < 16) {
Table[I] = (byte) ((Number + UnpOldTable20[I]) & 0xf);
I++;
} else if (Number == 16) {
N = (getbits() >>> 14) + 3;
addbits(2);
while (N-- > 0 && I < TableSize) {
Table[I] = Table[I - 1];
I++;
}
} else {
if (Number == 17) {
N = (getbits() >>> 13) + 3;
addbits(3);
} else {
N = (getbits() >>> 9) + 11;
addbits(7);
}
while (N-- > 0 && I < TableSize)
Table[I++] = 0;
}
}
if (inAddr > readTop) {
return (true);
}
if (UnpAudioBlock != 0)
for (I = 0; I < UnpChannels; I++)
makeDecodeTables(Table, I * Compress.MC20, MD[I], Compress.MC20);
else {
makeDecodeTables(Table, 0, LD, Compress.NC20);
makeDecodeTables(Table, Compress.NC20, DD, Compress.DC20);
makeDecodeTables(Table, Compress.NC20 + Compress.DC20, RD,
Compress.RC20);
}
// memcpy(UnpOldTable20,Table,sizeof(UnpOldTable20));
for (int i = 0; i < UnpOldTable20.length; i++) {
UnpOldTable20[i] = Table[i];
}
return (true);
}
protected void unpInitData20(boolean Solid)
{
if (!Solid) {
UnpChannelDelta = UnpCurChannel = 0;
UnpChannels = 1;
// memset(AudV,0,sizeof(AudV));
Arrays.fill(AudV, new AudioVariables());
// memset(UnpOldTable20,0,sizeof(UnpOldTable20));
Arrays.fill(UnpOldTable20, (byte) 0);
}
}
protected void ReadLastTables() throws IOException, RarException
{
if (readTop >= inAddr + 5) {
if (UnpAudioBlock != 0) {
if (decodeNumber(MD[UnpCurChannel]) == 256) {
ReadTables20();
}
} else {
if (decodeNumber(LD) == 269) {
ReadTables20();
}
}
}
}
protected byte DecodeAudio(int Delta)
{
AudioVariables v = AudV[UnpCurChannel];
v.setByteCount(v.getByteCount() + 1);
v.setD4(v.getD3());
v.setD3(v.getD2());// ->D3=V->D2;
v.setD2(v.getLastDelta() - v.getD1());// ->D2=V->LastDelta-V->D1;
v.setD1(v.getLastDelta());// V->D1=V->LastDelta;
// int PCh=8*V->LastChar+V->K1*V->D1 +V->K2*V->D2 +V->K3*V->D3
// +V->K4*V->D4+ V->K5*UnpChannelDelta;
int PCh = 8 * v.getLastChar() + v.getK1() * v.getD1();
PCh += v.getK2() * v.getD2() + v.getK3() * v.getD3();
PCh += v.getK4() * v.getD4() + v.getK5() * UnpChannelDelta;
PCh = (PCh >>> 3) & 0xFF;
int Ch = PCh - Delta;
int D = ((byte) Delta) << 3;
v.getDif()[0] += Math.abs(D);// V->Dif[0]+=abs(D);
v.getDif()[1] += Math.abs(D - v.getD1());// V->Dif[1]+=abs(D-V->D1);
v.getDif()[2] += Math.abs(D + v.getD1());// V->Dif[2]+=abs(D+V->D1);
v.getDif()[3] += Math.abs(D - v.getD2());// V->Dif[3]+=abs(D-V->D2);
v.getDif()[4] += Math.abs(D + v.getD2());// V->Dif[4]+=abs(D+V->D2);
v.getDif()[5] += Math.abs(D - v.getD3());// V->Dif[5]+=abs(D-V->D3);
v.getDif()[6] += Math.abs(D + v.getD3());// V->Dif[6]+=abs(D+V->D3);
v.getDif()[7] += Math.abs(D - v.getD4());// V->Dif[7]+=abs(D-V->D4);
v.getDif()[8] += Math.abs(D + v.getD4());// V->Dif[8]+=abs(D+V->D4);
v.getDif()[9] += Math.abs(D - UnpChannelDelta);// V->Dif[9]+=abs(D-UnpChannelDelta);
v.getDif()[10] += Math.abs(D + UnpChannelDelta);// V->Dif[10]+=abs(D+UnpChannelDelta);
v.setLastDelta((byte) (Ch - v.getLastChar()));
UnpChannelDelta = v.getLastDelta();
v.setLastChar(Ch);// V->LastChar=Ch;
if ((v.getByteCount() & 0x1F) == 0) {
int MinDif = v.getDif()[0], NumMinDif = 0;
v.getDif()[0] = 0;// ->Dif[0]=0;
for (int I = 1; I < v.getDif().length; I++) {
if (v.getDif()[I] < MinDif) {
MinDif = v.getDif()[I];
NumMinDif = I;
}
v.getDif()[I] = 0;
}
switch (NumMinDif) {
case 1:
if (v.getK1() >= -16) {
v.setK1(v.getK1() - 1);// V->K1--;
}
break;
case 2:
if (v.getK1() < 16) {
v.setK1(v.getK1() + 1);// V->K1++;
}
break;
case 3:
if (v.getK2() >= -16) {
v.setK2(v.getK2() - 1);// V->K2--;
}
break;
case 4:
if (v.getK2() < 16) {
v.setK2(v.getK2() + 1);// V->K2++;
}
break;
case 5:
if (v.getK3() >= -16) {
v.setK3(v.getK3() - 1);
}
break;
case 6:
if (v.getK3() < 16) {
v.setK3(v.getK3() + 1);
}
break;
case 7:
if (v.getK4() >= -16) {
v.setK4(v.getK4() - 1);
}
break;
case 8:
if (v.getK4() < 16) {
v.setK4(v.getK4() + 1);
}
break;
case 9:
if (v.getK5() >= -16) {
v.setK5(v.getK5() - 1);
}
break;
case 10:
if (v.getK5() < 16) {
v.setK5(v.getK5() + 1);
}
break;
}
}
return ((byte) Ch);
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/UnpackFilter.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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 com.github.junrar.unpack.vm.VMPreparedProgram;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class UnpackFilter {
private int BlockStart;
private int BlockLength;
private int ExecCount;
private boolean NextWindow;
// position of parent filter in Filters array used as prototype for filter
// in PrgStack array. Not defined for filters in Filters array.
private int ParentFilter;
private VMPreparedProgram Prg = new VMPreparedProgram();
public int getBlockLength() {
return BlockLength;
}
public void setBlockLength(int blockLength) {
BlockLength = blockLength;
}
public int getBlockStart() {
return BlockStart;
}
public void setBlockStart(int blockStart) {
BlockStart = blockStart;
}
public int getExecCount() {
return ExecCount;
}
public void setExecCount(int execCount) {
ExecCount = execCount;
}
public boolean isNextWindow() {
return NextWindow;
}
public void setNextWindow(boolean nextWindow) {
NextWindow = nextWindow;
}
public int getParentFilter() {
return ParentFilter;
}
public void setParentFilter(int parentFilter) {
ParentFilter = parentFilter;
}
public VMPreparedProgram getPrg() {
return Prg;
}
public void setPrg(VMPreparedProgram prg) {
Prg = prg;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/decode/AudioVariables.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.decode;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class AudioVariables {
int k1, k2, k3, k4, k5;
int d1, d2, d3, d4;
int lastDelta;
int dif[] = new int[11];
int byteCount;
int lastChar;
public int getByteCount() {
return byteCount;
}
public void setByteCount(int byteCount) {
this.byteCount = byteCount;
}
public int getD1() {
return d1;
}
public void setD1(int d1) {
this.d1 = d1;
}
public int getD2() {
return d2;
}
public void setD2(int d2) {
this.d2 = d2;
}
public int getD3() {
return d3;
}
public void setD3(int d3) {
this.d3 = d3;
}
public int getD4() {
return d4;
}
public void setD4(int d4) {
this.d4 = d4;
}
public int[] getDif() {
return dif;
}
public void setDif(int[] dif) {
this.dif = dif;
}
public int getK1() {
return k1;
}
public void setK1(int k1) {
this.k1 = k1;
}
public int getK2() {
return k2;
}
public void setK2(int k2) {
this.k2 = k2;
}
public int getK3() {
return k3;
}
public void setK3(int k3) {
this.k3 = k3;
}
public int getK4() {
return k4;
}
public void setK4(int k4) {
this.k4 = k4;
}
public int getK5() {
return k5;
}
public void setK5(int k5) {
this.k5 = k5;
}
public int getLastChar() {
return lastChar;
}
public void setLastChar(int lastChar) {
this.lastChar = lastChar;
}
public int getLastDelta() {
return lastDelta;
}
public void setLastDelta(int lastDelta) {
this.lastDelta = lastDelta;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/decode/BitDecode.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.decode;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class BitDecode extends Decode
{
/**
*
*/
public BitDecode()
{
decodeNum = new int[Compress.BC];
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/decode/CodeType.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.2007
*
* Source: $HeadURL$
* Last changed: $LastChangedDate$
*
* Here some html entities which can be used for escaping javadoc tags:
* "&": "&" or "&"
* "<": "<" or "<"
* ">": ">" or ">"
* "@": "@"
*/
package com.github.junrar.unpack.decode;
/**
* DOCUMENT ME
*
* 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
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public enum CodeType {
CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ,
CODE_STARTFILE,CODE_ENDFILE,CODE_VM,CODE_VMDATA;
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/decode/Compress.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.decode;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class Compress {
public static final int CODEBUFSIZE = 0x4000;
public static final int MAXWINSIZE = 0x400000;
public static final int MAXWINMASK = (MAXWINSIZE-1);
public static final int LOW_DIST_REP_COUNT = 16;
public static final int NC = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */
public static final int DC = 60;
public static final int LDC = 17;
public static final int RC = 28;
public static final int HUFF_TABLE_SIZE = (NC+DC+RC+LDC);
public static final int BC = 20;
public static final int NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */
public static final int DC20 = 48;
public static final int RC20 = 28;
public static final int BC20 = 19;
public static final int MC20 = 257;
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/decode/Decode.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.decode;
/**
* Used to store information for lz decoding
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class Decode
{
private int maxNum;
private final int[] decodeLen = new int[16];
private final int[] decodePos = new int[16];
protected int[] decodeNum = new int[2];
/**
* returns the decode Length array
* @return decodeLength
*/
public int[] getDecodeLen()
{
return decodeLen;
}
/**
* returns the decode num array
* @return decodeNum
*/
public int[] getDecodeNum()
{
return decodeNum;
}
/**
* returns the decodePos array
* @return decodePos
*/
public int[] getDecodePos()
{
return decodePos;
}
/**
* returns the max num
* @return maxNum
*/
public int getMaxNum()
{
return maxNum;
}
/**
* sets the max num
* @param maxNum to be set to maxNum
*/
public void setMaxNum(int maxNum)
{
this.maxNum = maxNum;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/decode/DistDecode.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.decode;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class DistDecode extends Decode
{
/**
*
*/
public DistDecode()
{
decodeNum = new int[Compress.DC];
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/decode/FilterType.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.decode;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public enum FilterType {
FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9,
FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
FILTER_ITANIUM, FILTER_E8E9V2;
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/decode/LitDecode.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.decode;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class LitDecode extends Decode
{
/**
*
*/
public LitDecode()
{
decodeNum = new int[Compress.NC];
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/decode/LowDistDecode.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.decode;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class LowDistDecode extends Decode
{
/**
*
*/
public LowDistDecode()
{
decodeNum = new int[Compress.LDC];
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/decode/MultDecode.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.decode;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class MultDecode extends Decode
{
/**
*
*/
public MultDecode()
{
decodeNum = new int[Compress.MC20];
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/decode/RepDecode.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.decode;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class RepDecode extends Decode
{
/**
*
*/
public RepDecode()
{
decodeNum = new int[Compress.RC];
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/AnalyzeHeapDump.java
================================================
package com.github.junrar.unpack.ppm;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* For debugging purposes only.
*
* @author alban
*/
public class AnalyzeHeapDump {
/** Creates a new instance of AnalyzeHeapDump */
public AnalyzeHeapDump() {
}
public static void main(String[] argv) {
File cfile = new File("P:\\test\\heapdumpc");
File jfile = new File("P:\\test\\heapdumpj");
if (!cfile.exists()) {
System.err.println("File not found: " + cfile.getAbsolutePath());
return;
}
if (!jfile.exists()) {
System.err.println("File not found: " + jfile.getAbsolutePath());
return;
}
long clen = cfile.length();
long jlen = jfile.length();
if (clen != jlen) {
System.out.println("File size mismatch");
System.out.println("clen = " + clen);
System.out.println("jlen = " + jlen);
}
// Do byte comparison
long len = Math.min(clen, jlen);
InputStream cin = null;
InputStream jin = null;
int bufferLen = 256*1024;
try {
cin = new BufferedInputStream(
new FileInputStream(cfile), bufferLen);
jin = new BufferedInputStream(
new FileInputStream(jfile), bufferLen);
boolean matching = true;
boolean mismatchFound = false;
long startOff = 0L;
long off = 0L;
while (off < len) {
if (cin.read() != jin.read()) {
if (matching) {
startOff = off;
matching = false;
mismatchFound = true;
}
}
else { // match
if (!matching) {
printMismatch(startOff, off);
matching = true;
}
}
off++;
}
if (!matching) {
printMismatch(startOff, off);
}
if (!mismatchFound) {
System.out.println("Files are identical");
}
System.out.println("Done");
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
cin.close();
jin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void printMismatch(long startOff, long bytesRead) {
System.out.println("Mismatch: off=" + startOff +
"(0x" + Long.toHexString(startOff) +
"), len=" + (bytesRead - startOff));
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/BlockTypes.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.ppm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public enum BlockTypes
{
BLOCK_LZ(0), BLOCK_PPM(1);
private int blockType;
private BlockTypes(int blockType)
{
this.blockType = blockType;
}
public int getBlockType()
{
return blockType;
}
public boolean equals(int blockType)
{
return this.blockType == blockType;
}
public static BlockTypes findBlockType(int blockType)
{
if (BLOCK_LZ.equals(blockType)) {
return BLOCK_LZ;
}
if (BLOCK_PPM.equals(blockType)) {
return BLOCK_PPM;
}
return null;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/FreqData.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 04.06.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.ppm;
import com.github.junrar.io.Raw;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class FreqData extends Pointer{
public static final int size = 6;
// struct FreqData
// {
// ushort SummFreq;
// STATE _PACK_ATTR * Stats;
// };
public FreqData(byte[]mem){
super(mem);
}
public FreqData init(byte[] mem) {
this.mem = mem;
pos = 0;
return this;
}
public int getSummFreq() {
return Raw.readShortLittleEndian(mem, pos)&0xffff;
}
public void setSummFreq(int summFreq) {
Raw.writeShortLittleEndian(mem, pos, (short)summFreq);
}
public void incSummFreq(int dSummFreq) {
Raw.incShortLittleEndian(mem, pos, dSummFreq);
}
public int getStats() {
return Raw.readIntLittleEndian(mem, pos+2);
}
public void setStats(State state) {
setStats(state.getAddress());
}
public void setStats(int state) {
Raw.writeIntLittleEndian(mem, pos+2, state);
}
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("FreqData[");
buffer.append("\n pos=");
buffer.append(pos);
buffer.append("\n size=");
buffer.append(size);
buffer.append("\n summFreq=");
buffer.append(getSummFreq());
buffer.append("\n stats=");
buffer.append(getStats());
buffer.append("\n]");
return buffer.toString();
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/ModelPPM.java
================================================
/*
* 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.ppm;
import java.io.IOException;
import java.util.Arrays;
import com.github.junrar.exception.RarException;
import com.github.junrar.unpack.Unpack;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class ModelPPM
{
public static final int MAX_O = 64; /* maximum allowed model order */
public static final int INT_BITS = 7;
public static final int PERIOD_BITS = 7;
public static final int TOT_BITS = INT_BITS + PERIOD_BITS;
public static final int INTERVAL = 1 << INT_BITS;
public static final int BIN_SCALE = 1 << TOT_BITS;
public static final int MAX_FREQ = 124;
private SEE2Context[][] SEE2Cont = new SEE2Context[25][16];
private SEE2Context dummySEE2Cont;
private PPMContext minContext, medContext, maxContext;
private State foundState; // found next state transition
private int numMasked, initEsc, orderFall, maxOrder, runLength, initRL;
private int[] charMask = new int[256];
private int[] NS2Indx = new int[256];
private int[] NS2BSIndx = new int[256];
private int[] HB2Flag = new int[256];
// byte EscCount, PrevSuccess, HiBitsFlag;
private int escCount, prevSuccess, hiBitsFlag;
private int[][] binSumm = new int[128][64]; // binary SEE-contexts
private RangeCoder coder = new RangeCoder();
private SubAllocator subAlloc = new SubAllocator();
private static int InitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3,
0x64A1, 0x5ABC, 0x6632, 0x6051 };
// Temp fields
private final State tempState1 = new State(null);
private final State tempState2 = new State(null);
private final State tempState3 = new State(null);
private final State tempState4 = new State(null);
private final StateRef tempStateRef1 = new StateRef();
private final StateRef tempStateRef2 = new StateRef();
private final PPMContext tempPPMContext1 = new PPMContext(null);
private final PPMContext tempPPMContext2 = new PPMContext(null);
private final PPMContext tempPPMContext3 = new PPMContext(null);
private final PPMContext tempPPMContext4 = new PPMContext(null);
private final int[] ps = new int[MAX_O];
public ModelPPM()
{
minContext = null;
maxContext = null;
medContext = null;
}
public SubAllocator getSubAlloc()
{
return subAlloc;
}
private void restartModelRare()
{
Arrays.fill(charMask, 0);
subAlloc.initSubAllocator();
initRL = -(maxOrder < 12 ? maxOrder : 12) - 1;
int addr = subAlloc.allocContext();
minContext.setAddress(addr);
maxContext.setAddress(addr);
minContext.setSuffix(0);
orderFall = maxOrder;
minContext.setNumStats(256);
minContext.getFreqData().setSummFreq(minContext.getNumStats()+1);
addr = subAlloc.allocUnits(256 / 2);
foundState.setAddress(addr);
minContext.getFreqData().setStats(addr);
State state = new State(subAlloc.getHeap());
addr = minContext.getFreqData().getStats();
runLength = initRL;
prevSuccess = 0;
for (int i = 0; i < 256; i++) {
state.setAddress(addr + i * State.size);
state.setSymbol(i);
state.setFreq(1);
state.setSuccessor(0);
}
for (int i = 0; i < 128; i++) {
for (int k = 0; k < 8; k++) {
for (int m = 0; m < 64; m += 8) {
binSumm[i][k + m] = BIN_SCALE - InitBinEsc[k] / (i + 2);
}
}
}
for (int i = 0; i < 25; i++) {
for (int k = 0; k < 16; k++) {
SEE2Cont[i][k].init(5 * i + 10);
}
}
}
private void startModelRare(int MaxOrder)
{
int i, k, m, Step;
escCount = 1;
this.maxOrder = MaxOrder;
restartModelRare();
// Bug Fixed
NS2BSIndx[0] = 0;
NS2BSIndx[1] = 2;
for (int j = 0; j < 9; j++) {
NS2BSIndx[2 + j] = 4;
}
for (int j = 0; j < 256 - 11; j++) {
NS2BSIndx[11 + j] = 6;
}
for (i = 0; i < 3; i++) {
NS2Indx[i] = i;
}
for (m = i, k = 1, Step = 1; i < 256; i++) {
NS2Indx[i] = m;
if ((--k) == 0) {
k = ++Step;
m++;
}
}
for (int j = 0; j < 0x40; j++) {
HB2Flag[j] = 0;
}
for (int j = 0; j < 0x100 - 0x40; j++) {
HB2Flag[0x40 + j] = 0x08;
}
dummySEE2Cont.setShift(PERIOD_BITS);
}
private void clearMask()
{
escCount = 1;
Arrays.fill(charMask, 0);
}
public boolean decodeInit(Unpack unpackRead, int escChar/* ref */)
throws IOException, RarException
{
int MaxOrder = unpackRead.getChar() & 0xff;
boolean reset = ((MaxOrder & 0x20) != 0);
int MaxMB = 0;
if (reset) {
MaxMB = unpackRead.getChar();
} else {
if (subAlloc.GetAllocatedMemory() == 0) {
return (false);
}
}
if ((MaxOrder & 0x40) != 0) {
escChar = unpackRead.getChar();
unpackRead.setPpmEscChar(escChar);
}
coder.initDecoder(unpackRead);
if (reset) {
MaxOrder = (MaxOrder & 0x1f) + 1;
if (MaxOrder > 16) {
MaxOrder = 16 + (MaxOrder - 16) * 3;
}
if (MaxOrder == 1) {
subAlloc.stopSubAllocator();
return (false);
}
subAlloc.startSubAllocator(MaxMB + 1);
minContext = new PPMContext(getHeap());
medContext = new PPMContext(getHeap());
maxContext = new PPMContext(getHeap());
foundState = new State(getHeap());
dummySEE2Cont = new SEE2Context();
for (int i = 0; i < 25; i++) {
for (int j = 0; j < 16; j++) {
SEE2Cont[i][j] = new SEE2Context();
}
}
startModelRare(MaxOrder);
}
return (minContext.getAddress() != 0);
}
public int decodeChar() throws IOException, RarException
{
// Debug
//subAlloc.dumpHeap();
if (minContext.getAddress() <= subAlloc.getPText()
|| minContext.getAddress() > subAlloc.getHeapEnd()) {
return (-1);
}
if (minContext.getNumStats() != 1) {
if (minContext.getFreqData().getStats() <= subAlloc.getPText()
|| minContext.getFreqData().getStats() > subAlloc.getHeapEnd()) {
return (-1);
}
if (!minContext.decodeSymbol1(this)) {
return (-1);
}
} else {
minContext.decodeBinSymbol(this);
}
coder.decode();
while (foundState.getAddress() == 0) {
coder.ariDecNormalize();
do {
orderFall++;
minContext.setAddress(minContext.getSuffix());// =MinContext->Suffix;
if (minContext.getAddress() <= subAlloc.getPText()
|| minContext.getAddress() > subAlloc.getHeapEnd()) {
return (-1);
}
} while (minContext.getNumStats() == numMasked);
if (!minContext.decodeSymbol2(this)) {
return (-1);
}
coder.decode();
}
int Symbol = foundState.getSymbol();
if ((orderFall == 0) && foundState.getSuccessor() > subAlloc.getPText()) {
// MinContext=MaxContext=FoundState->Successor;
int addr = foundState.getSuccessor();
minContext.setAddress(addr);
maxContext.setAddress(addr);
} else {
updateModel();
//this.foundState.setAddress(foundState.getAddress());//TODO just 4 debugging
if (escCount == 0) {
clearMask();
}
}
coder.ariDecNormalize();// ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
return (Symbol);
}
public SEE2Context[][] getSEE2Cont()
{
return SEE2Cont;
}
public SEE2Context getDummySEE2Cont()
{
return dummySEE2Cont;
}
public int getInitRL()
{
return initRL;
}
public void setEscCount(int escCount)
{
this.escCount = escCount&0xff;
}
public int getEscCount()
{
return escCount;
}
public void incEscCount(int dEscCount) {
setEscCount(getEscCount() + dEscCount);
}
public int[] getCharMask()
{
return charMask;
}
public int getNumMasked()
{
return numMasked;
}
public void setNumMasked(int numMasked)
{
this.numMasked = numMasked;
}
public void setPrevSuccess(int prevSuccess)
{
this.prevSuccess = prevSuccess&0xff;
}
public int getInitEsc()
{
return initEsc;
}
public void setInitEsc(int initEsc)
{
this.initEsc = initEsc;
}
public void setRunLength(int runLength)
{
this.runLength = runLength;
}
public int getRunLength()
{
return runLength;
}
public void incRunLength(int dRunLength) {
setRunLength(getRunLength() + dRunLength);
}
public int getPrevSuccess()
{
return prevSuccess;
}
public int getHiBitsFlag()
{
return hiBitsFlag;
}
public void setHiBitsFlag(int hiBitsFlag)
{
this.hiBitsFlag = hiBitsFlag&0xff;
}
public int[][] getBinSumm()
{
return binSumm;
}
public RangeCoder getCoder()
{
return coder;
}
public int[] getHB2Flag()
{
return HB2Flag;
}
public int[] getNS2BSIndx()
{
return NS2BSIndx;
}
public int[] getNS2Indx()
{
return NS2Indx;
}
public State getFoundState()
{
return foundState;
}
public byte[] getHeap()
{
return subAlloc.getHeap();
}
public int getOrderFall()
{
return orderFall;
}
private int /* ppmcontext ptr */createSuccessors(boolean Skip,
State p1 /* state ptr */) {
//State upState = tempState1.init(null);
StateRef upState = tempStateRef2;
State tempState = tempState1.init(getHeap());
// PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
PPMContext pc = tempPPMContext1.init(getHeap());
pc.setAddress(minContext.getAddress());
PPMContext upBranch = tempPPMContext2.init(getHeap());
upBranch.setAddress(foundState.getSuccessor());
// STATE * p, * ps[MAX_O], ** pps=ps;
State p = tempState2.init(getHeap());
int pps = 0;
boolean noLoop = false;
if (!Skip) {
ps[pps++] = foundState.getAddress();// *pps++ = FoundState;
if (pc.getSuffix() == 0) {
noLoop = true;
}
}
if (!noLoop) {
boolean loopEntry = false;
if (p1.getAddress() != 0) {
p.setAddress(p1.getAddress());
pc.setAddress(pc.getSuffix());// =pc->Suffix;
loopEntry = true;
}
do {
if (!loopEntry) {
pc.setAddress(pc.getSuffix());// pc=pc->Suffix;
if (pc.getNumStats() != 1) {
p.setAddress(pc.getFreqData().getStats());// p=pc->U.Stats
if (p.getSymbol() != foundState.getSymbol()) {
do {
p.incAddress();
} while (p.getSymbol() != foundState.getSymbol());
}
} else {
p.setAddress(pc.getOneState().getAddress());// p=&(pc->OneState);
}
}// LOOP_ENTRY:
loopEntry = false;
if (p.getSuccessor() != upBranch.getAddress()) {
pc.setAddress(p.getSuccessor());// =p->Successor;
break;
}
ps[pps++] = p.getAddress();
} while (pc.getSuffix() != 0);
} // NO_LOOP:
if (pps == 0) {
return pc.getAddress();
}
upState.setSymbol(getHeap()[upBranch.getAddress()]);// UpState.Symbol=*(byte*)
// UpBranch;
// UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1);
upState.setSuccessor(upBranch.getAddress() + 1); //TODO check if +1 necessary
if (pc.getNumStats() != 1) {
if (pc.getAddress() <= subAlloc.getPText()) {
return (0);
}
p.setAddress(pc.getFreqData().getStats());
if (p.getSymbol() != upState.getSymbol()) {
do {
p.incAddress();
} while (p.getSymbol() != upState.getSymbol());
}
int cf = p.getFreq() - 1;
int s0 = pc.getFreqData().getSummFreq() - pc.getNumStats() - cf;
// UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0)));
upState.setFreq(1 + ((2 * cf <= s0) ? (5 * cf > s0 ? 1 : 0) :
((2 * cf + 3 * s0 - 1) / (2 * s0))));
} else {
upState.setFreq(pc.getOneState().getFreq());// UpState.Freq=pc->OneState.Freq;
}
do {
// pc = pc->createChild(this,*--pps,UpState);
tempState.setAddress(ps[--pps]);
pc.setAddress(pc.createChild(this, tempState, upState));
if (pc.getAddress() == 0) {
return 0;
}
} while (pps != 0);
return pc.getAddress();
}
private void updateModelRestart()
{
restartModelRare();
escCount = 0;
}
private void updateModel()
{
//System.out.println("ModelPPM.updateModel()");
// STATE fs = *FoundState, *p = NULL;
StateRef fs = tempStateRef1;
fs.setValues(foundState);
State p = tempState3.init(getHeap());
State tempState = tempState4.init(getHeap());
PPMContext pc = tempPPMContext3.init(getHeap());
PPMContext successor = tempPPMContext4.init(getHeap());
int ns1, ns, cf, sf, s0;
pc.setAddress(minContext.getSuffix());
if (fs.getFreq() < MAX_FREQ / 4 && pc.getAddress() != 0) {
if (pc.getNumStats() != 1) {
p.setAddress(pc.getFreqData().getStats());
if (p.getSymbol() != fs.getSymbol()) {
do {
p.incAddress();
} while (p.getSymbol() != fs.getSymbol());
tempState.setAddress(p.getAddress() - State.size);
if (p.getFreq() >= tempState.getFreq()) {
State.ppmdSwap(p, tempState);
p.decAddress();
}
}
if (p.getFreq() < MAX_FREQ - 9) {
p.incFreq(2);
pc.getFreqData().incSummFreq(2);
}
} else {
p.setAddress(pc.getOneState().getAddress());
if (p.getFreq() < 32) {
p.incFreq(1);
}
}
}
if (orderFall == 0) {
foundState.setSuccessor(createSuccessors(true, p));
minContext.setAddress(foundState.getSuccessor());
maxContext.setAddress(foundState.getSuccessor());
if (minContext.getAddress() == 0) {
updateModelRestart();
return;
}
return;
}
subAlloc.getHeap()[subAlloc.getPText()] = (byte)fs.getSymbol();
subAlloc.incPText();
successor.setAddress(subAlloc.getPText());
if (subAlloc.getPText() >= subAlloc.getFakeUnitsStart()) {
updateModelRestart();
return;
}
// // Debug
// subAlloc.dumpHeap();
if (fs.getSuccessor() != 0) {
if (fs.getSuccessor() <= subAlloc.getPText()) {
fs.setSuccessor(createSuccessors(false, p));
if (fs.getSuccessor() == 0) {
updateModelRestart();
return;
}
}
if (--orderFall == 0) {
successor.setAddress(fs.getSuccessor());
if (maxContext.getAddress() != minContext.getAddress()) {
subAlloc.decPText(1);
}
}
}
else {
foundState.setSuccessor(successor.getAddress());
fs.setSuccessor(minContext);
}
// // Debug
// subAlloc.dumpHeap();
ns = minContext.getNumStats();
s0 = minContext.getFreqData().getSummFreq() - (ns) - (fs.getFreq() - 1);
for (pc.setAddress(maxContext.getAddress());
pc.getAddress() != minContext.getAddress();
pc.setAddress(pc.getSuffix())) {
if ((ns1 = pc.getNumStats()) != 1) {
if ((ns1 & 1) == 0) {
//System.out.println(ns1);
pc.getFreqData().setStats(
subAlloc.expandUnits(pc.getFreqData().getStats(),
ns1 >>> 1));
if (pc.getFreqData().getStats() == 0) {
updateModelRestart();
return;
}
}
// bug fixed
// int sum = ((2 * ns1 < ns) ? 1 : 0) +
// 2 * ((4 * ((ns1 <= ns) ? 1 : 0)) & ((pc.getFreqData()
// .getSummFreq() <= 8 * ns1) ? 1 : 0));
int sum = ((2 * ns1 < ns) ? 1 : 0) + 2 * (
((4 * ns1 <= ns) ? 1 : 0) &
((pc.getFreqData().getSummFreq() <= 8 * ns1) ? 1 : 0)
);
pc.getFreqData().incSummFreq(sum);
}
else {
p.setAddress(subAlloc.allocUnits(1));
if (p.getAddress() == 0) {
updateModelRestart();
return;
}
p.setValues(pc.getOneState());
pc.getFreqData().setStats(p);
if (p.getFreq() < MAX_FREQ / 4 - 1) {
p.incFreq(p.getFreq());
}
else {
p.setFreq(MAX_FREQ - 4);
}
pc.getFreqData().setSummFreq(
(p.getFreq() + initEsc + (ns > 3 ? 1 : 0)));
}
cf = 2 * fs.getFreq() * (pc.getFreqData().getSummFreq() + 6);
sf = s0 + pc.getFreqData().getSummFreq();
if (cf < 6 * sf) {
cf = 1 + (cf > sf ? 1 : 0) + (cf >= 4 * sf ? 1 : 0);
pc.getFreqData().incSummFreq(3);
}
else {
cf = 4 + (cf >= 9 * sf ? 1 : 0) + (cf >= 12 * sf ? 1 : 0) +
(cf >= 15 * sf ? 1 : 0);
pc.getFreqData().incSummFreq(cf);
}
p.setAddress(pc.getFreqData().getStats() + ns1*State.size);
p.setSuccessor(successor);
p.setSymbol(fs.getSymbol());
p.setFreq(cf);
pc.setNumStats(++ns1);
}
int address = fs.getSuccessor();
maxContext.setAddress(address);
minContext.setAddress(address);
//TODO-----debug
// int pos = minContext.getFreqData().getStats();
// State a = new State(getHeap());
// a.setAddress(pos);
// pos+=State.size;
// a.setAddress(pos);
//--dbg end
return;
}
// Debug
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("ModelPPM[");
buffer.append("\n numMasked=");
buffer.append(numMasked);
buffer.append("\n initEsc=");
buffer.append(initEsc);
buffer.append("\n orderFall=");
buffer.append(orderFall);
buffer.append("\n maxOrder=");
buffer.append(maxOrder);
buffer.append("\n runLength=");
buffer.append(runLength);
buffer.append("\n initRL=");
buffer.append(initRL);
buffer.append("\n escCount=");
buffer.append(escCount);
buffer.append("\n prevSuccess=");
buffer.append(prevSuccess);
buffer.append("\n foundState=");
buffer.append(foundState);
buffer.append("\n coder=");
buffer.append(coder);
buffer.append("\n subAlloc=");
buffer.append(subAlloc);
buffer.append("\n]");
return buffer.toString();
}
// Debug
// public void dumpHeap() {
// subAlloc.dumpHeap();
// }
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/PPMContext.java
================================================
/*
* 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.ppm;
import com.github.junrar.io.Raw;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class PPMContext extends Pointer
{
private static final int unionSize = Math.max(FreqData.size, State.size);
public static final int size = 2 + unionSize + 4; // 12
// ushort NumStats;
private int numStats; // determines if feqData or onstate is used
// (1==onestate)
private final FreqData freqData; // -\
// |-> union
private final State oneState; // -/
private int suffix; // pointer ppmcontext
public final static int[] ExpEscape =
{ 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
// Temp fields
private final State tempState1 = new State(null);
private final State tempState2 = new State(null);
private final State tempState3 = new State(null);
private final State tempState4 = new State(null);
private final State tempState5 = new State(null);
private PPMContext tempPPMContext = null;
private final int[] ps = new int[256];
public PPMContext(byte[] mem)
{
super(mem);
oneState = new State(mem);
freqData = new FreqData(mem);
}
public PPMContext init(byte[] mem) {
this.mem = mem;
pos = 0;
oneState.init(mem);
freqData.init(mem);
return this;
}
public FreqData getFreqData()
{
return freqData;
}
public void setFreqData(FreqData freqData)
{
this.freqData.setSummFreq(freqData.getSummFreq());
this.freqData.setStats(freqData.getStats());
}
public final int getNumStats()
{
if (mem!=null){
numStats = Raw.readShortLittleEndian(mem, pos)&0xffff;
}
return numStats;
}
public final void setNumStats(int numStats)
{
this.numStats = numStats&0xffff;
if (mem != null) {
Raw.writeShortLittleEndian(mem, pos, (short)numStats);
}
}
public State getOneState()
{
return oneState;
}
public void setOneState(StateRef oneState)
{
this.oneState.setValues(oneState);
}
public int getSuffix()
{
if(mem!=null){
suffix = Raw.readIntLittleEndian(mem, pos+8);
}
return suffix;
}
public void setSuffix(PPMContext suffix)
{
setSuffix(suffix.getAddress());
}
public void setSuffix(int suffix)
{
this.suffix = suffix;
if (mem != null) {
Raw.writeIntLittleEndian(mem, pos + 8, suffix);
}
}
@Override
public void setAddress(int pos)
{
super.setAddress(pos);
oneState.setAddress(pos+2);
freqData.setAddress(pos+2);
}
private PPMContext getTempPPMContext(byte[] mem) {
if (tempPPMContext == null) {
tempPPMContext = new PPMContext(null);
}
return tempPPMContext.init(mem);
}
public int createChild(ModelPPM model, State pStats/* ptr */,
StateRef firstState /* ref */)
{
PPMContext pc = getTempPPMContext(model.getSubAlloc().getHeap());
pc.setAddress(model.getSubAlloc().allocContext());
if (pc != null) {
pc.setNumStats(1);
pc.setOneState(firstState);
pc.setSuffix(this);
pStats.setSuccessor(pc);
}
return pc.getAddress();
}
public void rescale(ModelPPM model)
{
int OldNS = getNumStats(), i = getNumStats() - 1, Adder, EscFreq;
// STATE* p1, * p;
State p1 = new State(model.getHeap());
State p = new State(model.getHeap());
State temp = new State(model.getHeap());
for (p.setAddress(model.getFoundState().getAddress());
p.getAddress() != freqData.getStats();
p.decAddress()) {
temp.setAddress(p.getAddress() - State.size);
State.ppmdSwap(p, temp);
}
temp.setAddress(freqData.getStats());
temp.incFreq(4);
freqData.incSummFreq(4);
EscFreq = freqData.getSummFreq() - p.getFreq();
Adder = (model.getOrderFall() != 0) ? 1 : 0;
p.setFreq((p.getFreq() + Adder) >>> 1);
freqData.setSummFreq(p.getFreq());
do {
p.incAddress();
EscFreq -= p.getFreq();
p.setFreq((p.getFreq() + Adder) >>> 1);
freqData.incSummFreq(p.getFreq());
temp.setAddress(p.getAddress() - State.size);
if (p.getFreq() > temp.getFreq()) {
p1.setAddress(p.getAddress());
StateRef tmp = new StateRef();
tmp.setValues(p1);
State temp2 = new State(model.getHeap());
State temp3 = new State(model.getHeap());
do {
// p1[0]=p1[-1];
temp2.setAddress(p1.getAddress() - State.size);
p1.setValues(temp2);
p1.decAddress();
temp3.setAddress(p1.getAddress() - State.size);
} while (p1.getAddress() != freqData.getStats() && tmp.getFreq() > temp3.getFreq());
p1.setValues(tmp);
}
} while (--i != 0);
if (p.getFreq() == 0) {
do {
i++;
p.decAddress();
} while (p.getFreq() == 0);
EscFreq += i;
setNumStats(getNumStats() - i);
if (getNumStats() == 1) {
StateRef tmp = new StateRef();
temp.setAddress(freqData.getStats());
tmp.setValues(temp);
// STATE tmp=*U.Stats;
do {
// tmp.Freq-=(tmp.Freq >> 1)
tmp.decFreq(tmp.getFreq() >>> 1);
EscFreq >>>= 1;
} while (EscFreq > 1);
model.getSubAlloc().freeUnits(freqData.getStats(),(OldNS + 1) >>> 1);
oneState.setValues(tmp);
model.getFoundState().setAddress(oneState.getAddress());
return;
}
}
EscFreq -= EscFreq >>> 1;
freqData.incSummFreq(EscFreq);
int n0 = (OldNS + 1) >>> 1, n1 = (getNumStats() + 1) >>> 1;
if (n0 != n1) {
freqData.setStats(model.getSubAlloc().shrinkUnits(freqData.getStats(), n0, n1));
}
model.getFoundState().setAddress(freqData.getStats());
}
private int getArrayIndex(ModelPPM Model, State rs)
{
PPMContext tempSuffix = getTempPPMContext(Model.getSubAlloc().getHeap());
tempSuffix.setAddress(getSuffix());
int ret = 0;
ret += Model.getPrevSuccess();
ret += Model.getNS2BSIndx()[tempSuffix.getNumStats() - 1];
ret += Model.getHiBitsFlag() + 2* Model.getHB2Flag()[rs.getSymbol()];
ret += ((Model.getRunLength() >>> 26) & 0x20);
return ret;
}
public int getMean(int summ, int shift, int round)
{
return ( (summ + (1 << (shift - round) ) ) >>> (shift) );
}
public void decodeBinSymbol(ModelPPM model)
{
State rs = tempState1.init(model.getHeap());
rs.setAddress(oneState.getAddress());// State&
model.setHiBitsFlag(model.getHB2Flag()[model.getFoundState().getSymbol()]);
int off1 = rs.getFreq() - 1;
int off2 = getArrayIndex(model, rs);
int bs = model.getBinSumm()[off1][off2];
if (model.getCoder().getCurrentShiftCount(ModelPPM.TOT_BITS) < bs) {
model.getFoundState().setAddress(rs.getAddress());
rs.incFreq((rs.getFreq() < 128) ? 1 : 0);
model.getCoder().getSubRange().setLowCount(0);
model.getCoder().getSubRange().setHighCount(bs);
bs = ((bs + ModelPPM.INTERVAL - getMean(bs, ModelPPM.PERIOD_BITS, 2)) & 0xffff);
model.getBinSumm()[off1][off2] = bs;
model.setPrevSuccess(1);
model.incRunLength(1);
} else {
model.getCoder().getSubRange().setLowCount(bs);
bs = (bs - getMean(bs, ModelPPM.PERIOD_BITS, 2)) & 0xFFFF;
model.getBinSumm()[off1][off2] = bs;
model.getCoder().getSubRange().setHighCount(ModelPPM.BIN_SCALE);
model.setInitEsc(ExpEscape[bs >>> 10]);
model.setNumMasked(1);
model.getCharMask()[rs.getSymbol()] = model.getEscCount();
model.setPrevSuccess(0);
model.getFoundState().setAddress(0);
}
//int a = 0;//TODO just 4 debugging
}
// public static void ppmdSwap(ModelPPM model, StatePtr state1, StatePtr state2)
// {
// byte[] bytes = model.getSubAlloc().getHeap();
// int p1 = state1.getAddress();
// int p2 = state2.getAddress();
//
// for (int i = 0; i < StatePtr.size; i++) {
// byte temp = bytes[p1+i];
// bytes[p1+i] = bytes[p2+i];
// bytes[p2+i] = temp;
// }
// state1.setAddress(p1);
// state2.setAddress(p2);
// }
public void update1(ModelPPM model, int p/* ptr */)
{
model.getFoundState().setAddress(p);
model.getFoundState().incFreq(4);
freqData.incSummFreq(4);
State p0 = tempState3.init(model.getHeap());
State p1 = tempState4.init(model.getHeap());
p0.setAddress(p);
p1.setAddress(p - State.size);
if (p0.getFreq() > p1.getFreq()) {
State.ppmdSwap(p0, p1);
model.getFoundState().setAddress(p1.getAddress());
if (p1.getFreq() > ModelPPM.MAX_FREQ)
rescale(model);
}
}
public boolean decodeSymbol2(ModelPPM model)
{
long count;
int hiCnt, i = getNumStats() - model.getNumMasked();
SEE2Context psee2c = makeEscFreq2(model, i);
RangeCoder coder = model.getCoder();
// STATE* ps[256], ** pps=ps, * p=U.Stats-1;
State p = tempState1.init(model.getHeap());
State temp = tempState2.init(model.getHeap());
p.setAddress(freqData.getStats() - State.size);
int pps = 0;
hiCnt = 0;
do {
do {
p.incAddress();// p++;
} while (model.getCharMask()[p.getSymbol()] == model.getEscCount());
hiCnt += p.getFreq();
ps[pps++] = p.getAddress();
} while (--i != 0);
coder.getSubRange().incScale(hiCnt);
count = coder.getCurrentCount();
if (count >= coder.getSubRange().getScale()) {
return false;
}
pps = 0;
p.setAddress(ps[pps]);
if (count < hiCnt) {
hiCnt = 0;
while ((hiCnt += p.getFreq()) <= count) {
p.setAddress(ps[++pps]);// p=*++pps;
}
coder.getSubRange().setHighCount(hiCnt);
coder.getSubRange().setLowCount(hiCnt - p.getFreq());
psee2c.update();
update2(model, p.getAddress());
} else {
coder.getSubRange().setLowCount(hiCnt);
coder.getSubRange().setHighCount(coder.getSubRange().getScale());
i = getNumStats() - model.getNumMasked();// ->NumMasked;
pps--;
do {
temp.setAddress(ps[++pps]);// (*++pps)
model.getCharMask()[temp.getSymbol()] = model.getEscCount();
} while (--i != 0);
psee2c.incSumm((int)coder.getSubRange().getScale());
model.setNumMasked(getNumStats());
}
return (true);
}
public void update2(ModelPPM model, int p/* state ptr */)
{
State temp = tempState5.init(model.getHeap());
temp.setAddress(p);
model.getFoundState().setAddress(p);
model.getFoundState().incFreq(4);
freqData.incSummFreq(4);
if (temp.getFreq() > ModelPPM.MAX_FREQ) {
rescale(model);
}
model.incEscCount(1);
model.setRunLength(model.getInitRL());
}
private SEE2Context makeEscFreq2(ModelPPM model, int Diff)
{
SEE2Context psee2c;
int numStats = getNumStats();
if (numStats != 256) {
PPMContext suff = getTempPPMContext(model.getHeap());
suff.setAddress(getSuffix());
int idx1 = model.getNS2Indx()[Diff - 1];
int idx2 = 0;
idx2 += (Diff < suff.getNumStats() - numStats) ? 1 : 0;
idx2 += 2 * ((freqData.getSummFreq() < 11 * numStats) ? 1 : 0);
idx2 += 4 * ((model.getNumMasked() > Diff) ? 1 : 0);
idx2 += model.getHiBitsFlag();
psee2c = model.getSEE2Cont()[idx1][idx2];
model.getCoder().getSubRange().setScale(psee2c.getMean());
} else {
psee2c = model.getDummySEE2Cont();
model.getCoder().getSubRange().setScale(1);
}
return psee2c;
}
public boolean decodeSymbol1(ModelPPM model)
{
RangeCoder coder = model.getCoder();
coder.getSubRange().setScale(freqData.getSummFreq());
State p = new State(model.getHeap());
p.setAddress(freqData.getStats());
int i, HiCnt;
long count = coder.getCurrentCount();
if (count >= coder.getSubRange().getScale()) {
return false;
}
if (count < (HiCnt = p.getFreq())) {
coder.getSubRange().setHighCount(HiCnt);
model.setPrevSuccess((2 * HiCnt > coder.getSubRange().getScale()) ? 1 : 0);
model.incRunLength(model.getPrevSuccess());
HiCnt += 4;
model.getFoundState().setAddress(p.getAddress());
model.getFoundState().setFreq(HiCnt);
freqData.incSummFreq(4);
if (HiCnt > ModelPPM.MAX_FREQ) {
rescale(model);
}
coder.getSubRange().setLowCount(0);
return true;
} else {
if (model.getFoundState().getAddress() == 0) {
return (false);
}
}
model.setPrevSuccess(0);
int numStats = getNumStats();
i = numStats - 1;
while ((HiCnt += p.incAddress().getFreq()) <= count)
{
if (--i == 0) {
model.setHiBitsFlag(model.getHB2Flag()[model.getFoundState().getSymbol()]);
coder.getSubRange().setLowCount(HiCnt);
model.getCharMask()[p.getSymbol()] = model.getEscCount();
model.setNumMasked(numStats);
i = numStats - 1;
model.getFoundState().setAddress(0);
do {
model.getCharMask()[p.decAddress().getSymbol()] = model.getEscCount();
} while (--i != 0);
coder.getSubRange().setHighCount(coder.getSubRange().getScale());
return (true);
}
}
coder.getSubRange().setLowCount(HiCnt-p.getFreq());
coder.getSubRange().setHighCount(HiCnt);
update1(model, p.getAddress());
return (true);
}
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("PPMContext[");
buffer.append("\n pos=");
buffer.append(pos);
buffer.append("\n size=");
buffer.append(size);
buffer.append("\n numStats=");
buffer.append(getNumStats());
buffer.append("\n Suffix=");
buffer.append(getSuffix());
buffer.append("\n freqData=");
buffer.append(freqData);
buffer.append("\n oneState=");
buffer.append(oneState);
buffer.append("\n]");
return buffer.toString();
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/Pointer.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 14.06.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.ppm;
/**
* Simulates Pointers on a single mem block as a byte[]
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public abstract class Pointer
{
protected byte[] mem;
protected int pos;
/**
* Initialize the object with the array (may be null)
* @param mem the byte array
*/
public Pointer(byte[] mem){
this.mem = mem;
}
/**
* returns the position of this object in the byte[]
* @return the address of this object
*/
public int getAddress(){
assert (mem != null);
return pos;
}
/**
* needs to set the fields of this object to the values in the byte[]
* at the given position.
* be aware of the byte order
* @param pos the position this object should point to
* @return true if the address could be set
*/
public void setAddress(int pos) {
assert (mem != null);
assert (pos >= 0) && (pos < mem.length) : pos;
this.pos = pos;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/RangeCoder.java
================================================
/*
* 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.ppm;
import java.io.IOException;
import com.github.junrar.exception.RarException;
import com.github.junrar.unpack.Unpack;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class RangeCoder
{
public static final int TOP = 1 << 24;
public static final int BOT = 1 << 15;
private static final long uintMask = 0xFFFFffffL;
// uint low, code, range;
private long low, code, range;
private final SubRange subRange = new SubRange();
private Unpack unpackRead;
public SubRange getSubRange()
{
return subRange;
}
public void initDecoder(Unpack unpackRead) throws IOException, RarException
{
this.unpackRead = unpackRead;
low = code = 0L;
range = 0xFFFFffffL;
for (int i = 0; i < 4; i++) {
code = ((code << 8) | getChar())&uintMask;
}
}
public int getCurrentCount()
{
range = (range / subRange.getScale())&uintMask;
return (int)((code - low) / (range));
}
public long getCurrentShiftCount(int SHIFT)
{
range = range >>>SHIFT;
return ((code - low) / (range))&uintMask;
}
public void decode()
{
low = (low + (range * subRange.getLowCount()))&uintMask;
range = (range * (subRange.getHighCount() - subRange.getLowCount()))&uintMask;
}
private int getChar() throws IOException, RarException
{
return (unpackRead.getChar());
}
public void ariDecNormalize() throws IOException, RarException
{
// while ((low ^ (low + range)) < TOP || range < BOT && ((range = -low & (BOT - 1)) != 0 ? true : true))
// {
// code = ((code << 8) | unpackRead.getChar()&0xff)&uintMask;
// range = (range << 8)&uintMask;
// low = (low << 8)&uintMask;
// }
// Rewrote for clarity
boolean c2 = false;
while ((low ^ (low + range)) < TOP || (c2 = range < BOT)) {
if (c2) {
range = (-low & (BOT - 1))&uintMask;
c2 = false;
}
code = ((code << 8) | getChar())&uintMask;
range = (range << 8)&uintMask;
low = (low << 8)&uintMask;
}
}
// Debug
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("RangeCoder[");
buffer.append("\n low=");
buffer.append(low);
buffer.append("\n code=");
buffer.append(code);
buffer.append("\n range=");
buffer.append(range);
buffer.append("\n subrange=");
buffer.append(subRange);
buffer.append("]");
return buffer.toString();
}
public static class SubRange
{
// uint LowCount, HighCount, scale;
private long lowCount, highCount, scale;
public long getHighCount()
{
return highCount;
}
public void setHighCount(long highCount)
{
this.highCount = highCount&uintMask;
}
public long getLowCount()
{
return lowCount&uintMask;
}
public void setLowCount(long lowCount)
{
this.lowCount = lowCount&uintMask;
}
public long getScale()
{
return scale;
}
public void setScale(long scale)
{
this.scale = scale&uintMask;
}
public void incScale(int dScale) {
setScale(getScale() + dScale);
}
// Debug
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("SubRange[");
buffer.append("\n lowCount=");
buffer.append(lowCount);
buffer.append("\n highCount=");
buffer.append(highCount);
buffer.append("\n scale=");
buffer.append(scale);
buffer.append("]");
return buffer.toString();
}
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/RarMemBlock.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 05.06.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.ppm;
import com.github.junrar.io.Raw;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class RarMemBlock extends Pointer
{
public static final int size = 12;
private int stamp, NU;
private int next, prev; // Pointer RarMemBlock
public RarMemBlock(byte[] mem)
{
super(mem);
}
public void insertAt(RarMemBlock p)
{
RarMemBlock temp = new RarMemBlock(mem);
setPrev(p.getAddress());
temp.setAddress(getPrev());
setNext(temp.getNext());// prev.getNext();
temp.setNext(this);// prev.setNext(this);
temp.setAddress(getNext());
temp.setPrev(this);// next.setPrev(this);
}
public void remove()
{
RarMemBlock temp = new RarMemBlock(mem);
temp.setAddress(getPrev());
temp.setNext(getNext());// prev.setNext(next);
temp.setAddress(getNext());
temp.setPrev(getPrev());// next.setPrev(prev);
// next = -1;
// prev = -1;
}
public int getNext()
{
if(mem!=null){
next = Raw.readIntLittleEndian(mem, pos+4);
}
return next;
}
public void setNext(RarMemBlock next)
{
setNext(next.getAddress());
}
public void setNext(int next)
{
this.next = next;
if (mem != null) {
Raw.writeIntLittleEndian(mem, pos + 4, next);
}
}
public int getNU()
{
if(mem!=null){
NU = Raw.readShortLittleEndian(mem, pos+2)&0xffff;
}
return NU;
}
public void setNU(int nu)
{
NU = nu&0xffff;
if (mem != null) {
Raw.writeShortLittleEndian(mem, pos + 2, (short)nu);
}
}
public int getPrev()
{
if(mem!=null){
prev = Raw.readIntLittleEndian(mem, pos+8);
}
return prev;
}
public void setPrev(RarMemBlock prev)
{
setPrev(prev.getAddress());
}
public void setPrev(int prev)
{
this.prev = prev;
if (mem != null) {
Raw.writeIntLittleEndian(mem, pos + 8, prev);
}
}
public int getStamp()
{
if(mem!=null){
stamp = Raw.readShortLittleEndian(mem, pos)&0xffff;
}
return stamp;
}
public void setStamp(int stamp)
{
this.stamp = stamp;
if (mem != null) {
Raw.writeShortLittleEndian(mem, pos, (short)stamp);
}
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/RarNode.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 05.06.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.ppm;
import com.github.junrar.io.Raw;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class RarNode extends Pointer{
private int next; //rarnode pointer
public static final int size = 4;
public RarNode(byte[] mem){
super(mem);
}
public int getNext() {
if(mem!=null){
next = Raw.readIntLittleEndian(mem, pos);
}
return next;
}
public void setNext(RarNode next) {
setNext(next.getAddress());
}
public void setNext(int next) {
this.next = next;
if(mem!=null){
Raw.writeIntLittleEndian(mem, pos, next);
}
}
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("State[");
buffer.append("\n pos=");
buffer.append(pos);
buffer.append("\n size=");
buffer.append(size);
buffer.append("\n next=");
buffer.append(getNext());
buffer.append("\n]");
return buffer.toString();
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/SEE2Context.java
================================================
/*
* 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.ppm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class SEE2Context {
public static final int size = 4;
// ushort Summ;
private int summ;
// byte Shift;
private int shift;
// byte Count;
private int count;
public void init(int initVal) {
shift = (ModelPPM.PERIOD_BITS - 4)&0xff;
summ = (initVal << shift)&0xffff;
count = 4;
}
public int getMean() {
int retVal = summ >>> shift;
summ -= retVal;
return retVal + ((retVal == 0) ? 1 : 0);
}
public void update() {
if (shift < ModelPPM.PERIOD_BITS && --count == 0) {
summ += summ;
count = (3 << shift++);
}
summ &= 0xffff;
count &= 0xff;
shift &= 0xff;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count&0xff;
}
public int getShift() {
return shift;
}
public void setShift(int shift) {
this.shift = shift&0xff;
}
public int getSumm() {
return summ;
}
public void setSumm(int summ) {
this.summ = summ&0xffff;
}
public void incSumm(int dSumm) {
setSumm(getSumm() + dSumm);
}
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("SEE2Context[");
buffer.append("\n size=");
buffer.append(size);
buffer.append("\n summ=");
buffer.append(summ);
buffer.append("\n shift=");
buffer.append(shift);
buffer.append("\n count=");
buffer.append(count);
buffer.append("\n]");
return buffer.toString();
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/State.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.ppm;
import com.github.junrar.io.Raw;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class State extends Pointer {
public static final int size = 6;
public State(byte[] mem) {
super(mem);
}
public State init(byte[] mem) {
this.mem = mem;
pos = 0;
return this;
}
public int getSymbol() {
return mem[pos]&0xff;
}
public void setSymbol(int symbol) {
mem[pos] = (byte)symbol;
}
public int getFreq() {
return mem[pos+1]&0xff;
}
public void setFreq(int freq) {
mem[pos + 1] = (byte)freq;
}
public void incFreq(int dFreq) {
mem[pos + 1] += dFreq;
}
public int getSuccessor() {
return Raw.readIntLittleEndian(mem, pos+2);
}
public void setSuccessor(PPMContext successor) {
setSuccessor(successor.getAddress());
}
public void setSuccessor(int successor) {
Raw.writeIntLittleEndian(mem, pos + 2, successor);
}
public void setValues(StateRef state){
setSymbol(state.getSymbol());
setFreq(state.getFreq());
setSuccessor(state.getSuccessor());
}
public void setValues(State ptr){
System.arraycopy(ptr.mem, ptr.pos, mem, pos, size);
}
public State decAddress(){
setAddress(pos-size);
return this;
}
public State incAddress(){
setAddress(pos+size);
return this;
}
public static void ppmdSwap(State ptr1, State ptr2) {
byte[] mem1=ptr1.mem, mem2=ptr2.mem;
for (int i=0, pos1=ptr1.pos, pos2=ptr2.pos; i < size; i++, pos1++, pos2++) {
byte temp = mem1[pos1];
mem1[pos1] = mem2[pos2];
mem2[pos2] = temp;
}
}
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("State[");
buffer.append("\n pos=");
buffer.append(pos);
buffer.append("\n size=");
buffer.append(size);
buffer.append("\n symbol=");
buffer.append(getSymbol());
buffer.append("\n freq=");
buffer.append(getFreq());
buffer.append("\n successor=");
buffer.append(getSuccessor());
buffer.append("\n]");
return buffer.toString();
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/StateRef.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 01.06.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.ppm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class StateRef {
private int symbol;
private int freq;
private int successor; // pointer ppmcontext
public StateRef() {
}
public int getSymbol() {
return symbol;
}
public void setSymbol(int symbol) {
this.symbol = symbol&0xff;
}
public int getFreq() {
return freq;
}
public void setFreq(int freq) {
this.freq = freq&0xff;
}
public void incFreq(int dFreq) {
freq = (freq + dFreq)&0xff;
}
public void decFreq(int dFreq) {
freq = (freq - dFreq)&0xff;
}
public void setValues(State statePtr){
setFreq(statePtr.getFreq());
setSuccessor(statePtr.getSuccessor());
setSymbol(statePtr.getSymbol());
}
public int getSuccessor() {
return successor;
}
public void setSuccessor(PPMContext successor) {
setSuccessor(successor.getAddress());
}
public void setSuccessor(int successor) {
this.successor = successor;
}
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("State[");
buffer.append("\n symbol=");
buffer.append(getSymbol());
buffer.append("\n freq=");
buffer.append(getFreq());
buffer.append("\n successor=");
buffer.append(getSuccessor());
buffer.append("\n]");
return buffer.toString();
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/ppm/SubAllocator.java
================================================
/*
* 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.ppm;
import java.util.Arrays;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class SubAllocator {
public static final int N1 = 4, N2 = 4, N3 = 4, N4 = (128 + 3 - 1 * N1 - 2
* N2 - 3 * N3) / 4;
public static final int N_INDEXES = N1 + N2 + N3 + N4;
public static final int UNIT_SIZE = Math.max(PPMContext.size,
RarMemBlock.size);
public static final int FIXED_UNIT_SIZE = 12;
private int subAllocatorSize;
// byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
private int[] indx2Units = new int[N_INDEXES];
private int[] units2Indx = new int[128];
private int glueCount;
// byte *HeapStart,*LoUnit, *HiUnit;
private int heapStart, loUnit, hiUnit;
private final RarNode[] freeList = new RarNode[N_INDEXES];
// byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart;
private int pText, unitsStart, heapEnd, fakeUnitsStart;
private byte[] heap;
private int freeListPos;
private int tempMemBlockPos;
// Temp fields
private RarNode tempRarNode = null;
private RarMemBlock tempRarMemBlock1 = null;
private RarMemBlock tempRarMemBlock2 = null;
private RarMemBlock tempRarMemBlock3 = null;
public SubAllocator() {
clean();
}
public void clean() {
subAllocatorSize = 0;
}
private void insertNode(int p/* rarnode ptr */, int indx) {
RarNode temp = tempRarNode;
temp.setAddress(p);
temp.setNext(freeList[indx].getNext());
freeList[indx].setNext(temp);
}
public void incPText() {
pText++;
}
private int removeNode(int indx) {
int retVal = freeList[indx].getNext();
RarNode temp = tempRarNode;
temp.setAddress(retVal);
freeList[indx].setNext(temp.getNext());
return retVal;
}
private int U2B(int NU) {
return /* 8*NU+4*NU */UNIT_SIZE * NU;
}
/* memblockptr */
private int MBPtr(int BasePtr, int Items) {
return (BasePtr + U2B(Items));
}
private void splitBlock(int pv/* ptr */, int oldIndx, int newIndx) {
int i, uDiff = indx2Units[oldIndx] - indx2Units[newIndx];
int p = pv + U2B(indx2Units[newIndx]);
if (indx2Units[i = units2Indx[uDiff - 1]] != uDiff) {
insertNode(p, --i);
p += U2B(i = indx2Units[i]);
uDiff -= i;
}
insertNode(p, units2Indx[uDiff - 1]);
}
public void stopSubAllocator() {
if (subAllocatorSize != 0) {
subAllocatorSize = 0;
heap = null;
heapStart = 1;
// rarfree(HeapStart);
// Free temp fields
tempRarNode = null;
tempRarMemBlock1 = null;
tempRarMemBlock2 = null;
tempRarMemBlock3 = null;
}
}
public int GetAllocatedMemory() {
return subAllocatorSize;
};
public boolean startSubAllocator(int SASize) {
int t = SASize << 20;
if (subAllocatorSize == t) {
return true;
}
stopSubAllocator();
int allocSize = t / FIXED_UNIT_SIZE * UNIT_SIZE + UNIT_SIZE;
// adding space for freelist (needed for poiters)
// 1+ for null pointer
int realAllocSize = 1 + allocSize + 4 * N_INDEXES;
// adding space for an additional memblock
tempMemBlockPos = realAllocSize;
realAllocSize += RarMemBlock.size;
heap = new byte[realAllocSize];
heapStart = 1;
heapEnd = heapStart + allocSize - UNIT_SIZE;
subAllocatorSize = t;
// Bug fixed
freeListPos = heapStart + allocSize;
assert (realAllocSize - tempMemBlockPos == RarMemBlock.size) : realAllocSize
+ " " + tempMemBlockPos + " " + RarMemBlock.size;
// Init freeList
for (int i = 0, pos = freeListPos; i < freeList.length; i++, pos += RarNode.size) {
freeList[i] = new RarNode(heap);
freeList[i].setAddress(pos);
}
// Init temp fields
tempRarNode = new RarNode(heap);
tempRarMemBlock1 = new RarMemBlock(heap);
tempRarMemBlock2 = new RarMemBlock(heap);
tempRarMemBlock3 = new RarMemBlock(heap);
return true;
}
private void glueFreeBlocks() {
RarMemBlock s0 = tempRarMemBlock1;
s0.setAddress(tempMemBlockPos);
RarMemBlock p = tempRarMemBlock2;
RarMemBlock p1 = tempRarMemBlock3;
int i, k, sz;
if (loUnit != hiUnit) {
heap[loUnit] = 0;
}
for (i = 0, s0.setPrev(s0), s0.setNext(s0); i < N_INDEXES; i++) {
while (freeList[i].getNext() != 0) {
p.setAddress(removeNode(i));// =(RAR_MEM_BLK*)RemoveNode(i);
p.insertAt(s0);// p->insertAt(&s0);
p.setStamp(0xFFFF);// p->Stamp=0xFFFF;
p.setNU(indx2Units[i]);// p->NU=Indx2Units[i];
}
}
for (p.setAddress(s0.getNext()); p.getAddress() != s0.getAddress(); p
.setAddress(p.getNext())) {
// while ((p1=MBPtr(p,p->NU))->Stamp == 0xFFFF && int(p->NU)+p1->NU
// < 0x10000)
// Bug fixed
p1.setAddress(MBPtr(p.getAddress(), p.getNU()));
while (p1.getStamp() == 0xFFFF && p.getNU() + p1.getNU() < 0x10000) {
p1.remove();
p.setNU(p.getNU() + p1.getNU());// ->NU += p1->NU;
p1.setAddress(MBPtr(p.getAddress(), p.getNU()));
}
}
// while ((p=s0.next) != &s0)
// Bug fixed
p.setAddress(s0.getNext());
while (p.getAddress() != s0.getAddress()) {
for (p.remove(), sz = p.getNU(); sz > 128; sz -= 128, p
.setAddress(MBPtr(p.getAddress(), 128))) {
insertNode(p.getAddress(), N_INDEXES - 1);
}
if (indx2Units[i = units2Indx[sz - 1]] != sz) {
k = sz - indx2Units[--i];
insertNode(MBPtr(p.getAddress(), sz - k), k - 1);
}
insertNode(p.getAddress(), i);
p.setAddress(s0.getNext());
}
}
private int allocUnitsRare(int indx) {
if (glueCount == 0) {
glueCount = 255;
glueFreeBlocks();
if (freeList[indx].getNext() != 0) {
return removeNode(indx);
}
}
int i = indx;
do {
if (++i == N_INDEXES) {
glueCount--;
i = U2B(indx2Units[indx]);
int j = FIXED_UNIT_SIZE * indx2Units[indx];
if (fakeUnitsStart - pText > j) {
fakeUnitsStart -= j;
unitsStart -= i;
return unitsStart;
}
return (0);
}
} while (freeList[i].getNext() == 0);
int retVal = removeNode(i);
splitBlock(retVal, i, indx);
return retVal;
}
public int allocUnits(int NU) {
int indx = units2Indx[NU - 1];
if (freeList[indx].getNext() != 0) {
return removeNode(indx);
}
int retVal = loUnit;
loUnit += U2B(indx2Units[indx]);
if (loUnit <= hiUnit) {
return retVal;
}
loUnit -= U2B(indx2Units[indx]);
return allocUnitsRare(indx);
}
public int allocContext() {
if (hiUnit != loUnit)
return (hiUnit -= UNIT_SIZE);
if (freeList[0].getNext() != 0) {
return removeNode(0);
}
return allocUnitsRare(0);
}
public int expandUnits(int oldPtr, int OldNU) {
int i0 = units2Indx[OldNU - 1];
int i1 = units2Indx[OldNU - 1 + 1];
if (i0 == i1) {
return oldPtr;
}
int ptr = allocUnits(OldNU + 1);
if (ptr != 0) {
// memcpy(ptr,OldPtr,U2B(OldNU));
System.arraycopy(heap, oldPtr, heap, ptr, U2B(OldNU));
insertNode(oldPtr, i0);
}
return ptr;
}
public int shrinkUnits(int oldPtr, int oldNU, int newNU) {
// System.out.println("SubAllocator.shrinkUnits(" + OldPtr + ", " +
// OldNU + ", " + NewNU + ")");
int i0 = units2Indx[oldNU - 1];
int i1 = units2Indx[newNU - 1];
if (i0 == i1) {
return oldPtr;
}
if (freeList[i1].getNext() != 0) {
int ptr = removeNode(i1);
// memcpy(ptr,OldPtr,U2B(NewNU));
// for (int i = 0; i < U2B(NewNU); i++) {
// heap[ptr + i] = heap[OldPtr + i];
// }
System.arraycopy(heap, oldPtr, heap, ptr, U2B(newNU));
insertNode(oldPtr, i0);
return ptr;
} else {
splitBlock(oldPtr, i0, i1);
return oldPtr;
}
}
public void freeUnits(int ptr, int OldNU) {
insertNode(ptr, units2Indx[OldNU - 1]);
}
public int getFakeUnitsStart() {
return fakeUnitsStart;
}
public void setFakeUnitsStart(int fakeUnitsStart) {
this.fakeUnitsStart = fakeUnitsStart;
}
public int getHeapEnd() {
return heapEnd;
}
public int getPText() {
return pText;
}
public void setPText(int text) {
pText = text;
}
public void decPText(int dPText) {
setPText(getPText() - dPText);
}
public int getUnitsStart() {
return unitsStart;
}
public void setUnitsStart(int unitsStart) {
this.unitsStart = unitsStart;
}
public void initSubAllocator() {
int i, k;
Arrays
.fill(heap, freeListPos, freeListPos + sizeOfFreeList(),
(byte) 0);
pText = heapStart;
int size2 = FIXED_UNIT_SIZE
* (subAllocatorSize / 8 / FIXED_UNIT_SIZE * 7);
int realSize2 = size2 / FIXED_UNIT_SIZE * UNIT_SIZE;
int size1 = subAllocatorSize - size2;
int realSize1 = size1 / FIXED_UNIT_SIZE * UNIT_SIZE + size1
% FIXED_UNIT_SIZE;
hiUnit = heapStart + subAllocatorSize;
loUnit = unitsStart = heapStart + realSize1;
fakeUnitsStart = heapStart + size1;
hiUnit = loUnit + realSize2;
for (i = 0, k = 1; i < N1; i++, k += 1) {
indx2Units[i] = k & 0xff;
}
for (k++; i < N1 + N2; i++, k += 2) {
indx2Units[i] = k & 0xff;
}
for (k++; i < N1 + N2 + N3; i++, k += 3) {
indx2Units[i] = k & 0xff;
}
for (k++; i < (N1 + N2 + N3 + N4); i++, k += 4) {
indx2Units[i] = k & 0xff;
}
for (glueCount = 0, k = 0, i = 0; k < 128; k++) {
i += ((indx2Units[i] < (k + 1)) ? 1 : 0);
units2Indx[k] = i & 0xff;
}
}
private int sizeOfFreeList() {
return freeList.length * RarNode.size;
}
public byte[] getHeap() {
return heap;
}
// Debug
// public void dumpHeap() {
// File file = new File("P:\\test\\heapdumpj");
// OutputStream out = null;
// try {
// out = new FileOutputStream(file);
// out.write(heap, heapStart, heapEnd - heapStart);
// out.flush();
// System.out.println("Heap dumped to " + file.getAbsolutePath());
// }
// catch (IOException e) {
// e.printStackTrace();
// }
// finally {
// FileUtil.close(out);
// }
// }
// Debug
public String toString() {
StringBuilder buffer = new StringBuilder();
buffer.append("SubAllocator[");
buffer.append("\n subAllocatorSize=");
buffer.append(subAllocatorSize);
buffer.append("\n glueCount=");
buffer.append(glueCount);
buffer.append("\n heapStart=");
buffer.append(heapStart);
buffer.append("\n loUnit=");
buffer.append(loUnit);
buffer.append("\n hiUnit=");
buffer.append(hiUnit);
buffer.append("\n pText=");
buffer.append(pText);
buffer.append("\n unitsStart=");
buffer.append(unitsStart);
buffer.append("\n]");
return buffer.toString();
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/vm/BitInput.java
================================================
/*
* 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.vm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class BitInput {
/**
* the max size of the input
*/
public static final int MAX_SIZE = 0x8000;
protected int inAddr;
protected int inBit;
protected byte[] inBuf;
/**
*
*/
public void InitBitInput()
{
inAddr=0;
inBit=0;
}
/**
* @param Bits
*/
public void addbits(int Bits)
{
Bits+=inBit;
inAddr+=Bits>>3;
inBit=Bits&7;
}
/**
* @return the bits (unsigned short)
*/
public int getbits()
{
// int BitField=0;
// BitField|=(int)(inBuf[inAddr] << 16)&0xFF0000;
// BitField|=(int)(inBuf[inAddr+1] << 8)&0xff00;
// BitField|=(int)(inBuf[inAddr+2])&0xFF;
// BitField >>>= (8-inBit);
// return (BitField & 0xffff);
return (((((inBuf[inAddr] & 0xff) << 16) +
((inBuf[inAddr+1] & 0xff) << 8) +
((inBuf[inAddr+2] & 0xff))) >>> (8-inBit)) & 0xffff);
}
/**
*
*/
public BitInput()
{
inBuf=new byte[MAX_SIZE];
}
/**
* @param Bits add the bits
*/
public void faddbits(int Bits)
{
addbits(Bits);
}
/**
* @return get the bits
*/
public int fgetbits()
{
return(getbits());
}
/**
* Indicates an Overfow
* @param IncPtr how many bytes to inc
* @return true if an Oververflow would occur
*/
public boolean Overflow(int IncPtr) {
return(inAddr+IncPtr>=MAX_SIZE);
}
public byte[] getInBuf()
{
return inBuf;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/vm/RarVM.java
================================================
/*
* 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.vm;
import java.util.List;
import java.util.Vector;
import com.github.junrar.crc.RarCRC;
import com.github.junrar.io.Raw;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class RarVM extends BitInput {
public static final int VM_MEMSIZE = 0x40000;
public static final int VM_MEMMASK = (VM_MEMSIZE - 1);
public static final int VM_GLOBALMEMADDR = 0x3C000;
public static final int VM_GLOBALMEMSIZE = 0x2000;
public static final int VM_FIXEDGLOBALSIZE = 64;
private static final int regCount = 8;
private static final long UINT_MASK = 0xffffFFFF;//((long)2*(long)Integer.MAX_VALUE);
private byte[] mem;
private int[] R = new int[regCount];
private int flags;
private int maxOpCount = 25000000;
private int codeSize;
private int IP;
public RarVM() {
mem = null;
}
public void init() {
if (mem == null) {
mem = new byte[VM_MEMSIZE + 4];
}
}
private boolean isVMMem(byte[] mem) {
return this.mem == mem;
}
private int getValue(boolean byteMode, byte[] mem, int offset) {
if (byteMode) {
if (isVMMem(mem)) {
return (mem[offset]);
} else {
return (mem[offset] & 0xff);
}
} else {
if (isVMMem(mem)) {
//little
return Raw.readIntLittleEndian(mem, offset);
} else
//big endian
return Raw.readIntBigEndian(mem, offset);
}
}
private void setValue(boolean byteMode, byte[] mem, int offset, int value) {
if (byteMode) {
if (isVMMem(mem)) {
mem[offset] = (byte) value;
} else {
mem[offset] = (byte) ((mem[offset] & 0x00) | (byte) (value & 0xff));
}
} else {
if (isVMMem(mem)) {
Raw.writeIntLittleEndian(mem, offset, value);
// mem[offset + 0] = (byte) value;
// mem[offset + 1] = (byte) (value >>> 8);
// mem[offset + 2] = (byte) (value >>> 16);
// mem[offset + 3] = (byte) (value >>> 24);
} else {
Raw.writeIntBigEndian(mem, offset, value);
// mem[offset + 3] = (byte) value;
// mem[offset + 2] = (byte) (value >>> 8);
// mem[offset + 1] = (byte) (value >>> 16);
// mem[offset + 0] = (byte) (value >>> 24);
}
}
// #define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint
// *)Addr,Value)
}
public void setLowEndianValue(byte[] mem, int offset, int value) {
Raw.writeIntLittleEndian(mem, offset, value);
// mem[offset + 0] = (byte) (value&0xff);
// mem[offset + 1] = (byte) ((value >>> 8)&0xff);
// mem[offset + 2] = (byte) ((value >>> 16)&0xff);
// mem[offset + 3] = (byte) ((value >>> 24)&0xff);
}
public void setLowEndianValue(Vector mem, int offset, int value) {
mem.set(offset + 0, Byte.valueOf((byte) (value&0xff))) ;
mem.set(offset + 1, Byte.valueOf((byte) ((value >>> 8)&0xff)));
mem.set(offset + 2, Byte.valueOf((byte) ((value >>> 16)&0xff) ));
mem.set(offset + 3, Byte.valueOf((byte) ((value >>> 24)&0xff))) ;
}
private int getOperand(VMPreparedOperand cmdOp) {
int ret = 0;
if (cmdOp.getType() == VMOpType.VM_OPREGMEM) {
int pos = (cmdOp.getOffset() + cmdOp.getBase()) & VM_MEMMASK;
ret = Raw.readIntLittleEndian(mem, pos);
} else {
int pos = cmdOp.getOffset();
ret = Raw.readIntLittleEndian(mem, pos);
}
return ret;
}
public void execute(VMPreparedProgram prg) {
for (int i = 0; i < prg.getInitR().length; i++) // memcpy(R,Prg->InitR,sizeof(Prg->InitR));
{
R[i] = prg.getInitR()[i];
}
long globalSize = Math
.min(prg.getGlobalData().size(), VM_GLOBALMEMSIZE) & 0xffFFffFF;
if (globalSize != 0) {
for (int i = 0; i < globalSize; i++) // memcpy(Mem+VM_GLOBALMEMADDR,&Prg->GlobalData[0],GlobalSize);
{
mem[VM_GLOBALMEMADDR + i] = prg.getGlobalData().get(i);
}
}
long staticSize = Math.min(prg.getStaticData().size(), VM_GLOBALMEMSIZE
- globalSize) & 0xffFFffFF;
if (staticSize != 0) {
for (int i = 0; i < staticSize; i++) // memcpy(Mem+VM_GLOBALMEMADDR+GlobalSize,&Prg->StaticData[0],StaticSize);
{
mem[VM_GLOBALMEMADDR + (int) globalSize + i] = prg
.getStaticData().get(i);
}
}
R[7] = VM_MEMSIZE;
flags = 0;
List preparedCode = prg.getAltCmd().size() != 0 ? prg
.getAltCmd()
: prg.getCmd();
if (!ExecuteCode(preparedCode, prg.getCmdCount())) {
preparedCode.get(0).setOpCode(VMCommands.VM_RET);
}
int newBlockPos = getValue(false, mem, VM_GLOBALMEMADDR + 0x20)
& VM_MEMMASK;
int newBlockSize = getValue(false, mem, VM_GLOBALMEMADDR + 0x1c)
& VM_MEMMASK;
if ((newBlockPos + newBlockSize) >= VM_MEMSIZE) {
newBlockPos = 0;
newBlockSize = 0;
}
prg.setFilteredDataOffset(newBlockPos);
prg.setFilteredDataSize(newBlockSize);
prg.getGlobalData().clear();
int dataSize = Math.min(getValue(false, mem, VM_GLOBALMEMADDR + 0x30),
VM_GLOBALMEMSIZE - VM_FIXEDGLOBALSIZE);
if (dataSize != 0) {
prg.getGlobalData().setSize(dataSize + VM_FIXEDGLOBALSIZE);
// ->GlobalData.Add(dataSize+VM_FIXEDGLOBALSIZE);
for (int i = 0; i < dataSize + VM_FIXEDGLOBALSIZE; i++) // memcpy(&Prg->GlobalData[0],&Mem[VM_GLOBALMEMADDR],DataSize+VM_FIXEDGLOBALSIZE);
{
prg.getGlobalData().set(i, mem[VM_GLOBALMEMADDR + i]);
}
}
}
public byte[] getMem()
{
return mem;
}
private boolean setIP(int ip) {
if ((ip) >= codeSize) {
return (true);
}
if (--maxOpCount <= 0) {
return (false);
}
IP = ip;
return true;
}
private boolean ExecuteCode(List preparedCode,
int cmdCount) {
maxOpCount = 25000000;
this.codeSize = cmdCount;
this.IP = 0;
while (true) {
VMPreparedCommand cmd = preparedCode.get(IP);
int op1 = getOperand(cmd.getOp1());
int op2 = getOperand(cmd.getOp2());
switch (cmd.getOpCode()) {
case VM_MOV:
setValue(cmd.isByteMode(), mem, op1, getValue(cmd.isByteMode(),
mem, op2)); // SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2));
break;
case VM_MOVB:
setValue(true, mem, op1, getValue(true, mem, op2));
break;
case VM_MOVD:
setValue(false, mem, op1, getValue(false, mem, op2));
break;
case VM_CMP: {
int value1 = getValue(cmd.isByteMode(), mem, op1);
int result = value1 - getValue(cmd.isByteMode(), mem, op2);
if (result == 0) {
flags = VMFlags.VM_FZ.getFlag();
} else {
flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS
.getFlag());
}
}
break;
case VM_CMPB: {
int value1 = getValue(true, mem, op1);
int result = value1 - getValue(true, mem, op2);
if (result == 0) {
flags = VMFlags.VM_FZ.getFlag();
} else {
flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS
.getFlag());
}
}
break;
case VM_CMPD: {
int value1 = getValue(false, mem, op1);
int result = value1 - getValue(false, mem, op2);
if (result == 0) {
flags = VMFlags.VM_FZ.getFlag();
} else {
flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS
.getFlag());
}
}
break;
case VM_ADD: {
int value1 = getValue(cmd.isByteMode(), mem, op1);
int result = (int) ((((long) value1 + (long) getValue(cmd
.isByteMode(), mem, op2))) & 0xffffffff);
if (cmd.isByteMode()) {
result &= 0xff;
flags = (result < value1) ? 1
: 0 | (result == 0 ? VMFlags.VM_FZ.getFlag()
: ((result & 0x80) != 0) ? VMFlags.VM_FS
.getFlag() : 0);
// Flags=(Result value1) ? 1 : 0 | (result & VMFlags.VM_FS
.getFlag());
setValue(cmd.isByteMode(), mem, op1, result);// (Cmd->ByteMode,Op1,Result);
}
break;
case VM_SUBB:
setValue(true, mem, op1,
(int) ((long) getValue(true, mem, op1) & 0xFFffFFff
- (long) getValue(true, mem, op2) & 0xFFffFFff));
break;
case VM_SUBD:
setValue(
false,
mem,
op1,
(int) ((long) getValue(false, mem, op1) & 0xFFffFFff
- (long) getValue(false, mem, op2) & 0xFFffFFff));
break;
case VM_JZ:
if ((flags & VMFlags.VM_FZ.getFlag()) != 0) {
setIP(getValue(false, mem, op1));
continue;
}
break;
case VM_JNZ:
if ((flags & VMFlags.VM_FZ.getFlag()) == 0) {
setIP(getValue(false, mem, op1));
continue;
}
break;
case VM_INC: {
int result = (int) ((long) getValue(cmd.isByteMode(), mem, op1) & 0xFFffFFff + 1);
if (cmd.isByteMode()) {
result &= 0xff;
}
setValue(cmd.isByteMode(), mem, op1, result);
flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result
& VMFlags.VM_FS.getFlag();
}
break;
case VM_INCB:
setValue(
true,
mem,
op1,
(int) ((long) getValue(true, mem, op1) & 0xFFffFFff + 1));
break;
case VM_INCD:
setValue(false, mem, op1, (int) ((long) getValue(false, mem,
op1) & 0xFFffFFff + 1));
break;
case VM_DEC: {
int result = (int) ((long) getValue(cmd.isByteMode(), mem, op1) & 0xFFffFFff - 1);
setValue(cmd.isByteMode(), mem, op1, result);
flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result
& VMFlags.VM_FS.getFlag();
}
break;
case VM_DECB:
setValue(
true,
mem,
op1,
(int) ((long) getValue(true, mem, op1) & 0xFFffFFff - 1));
break;
case VM_DECD:
setValue(false, mem, op1, (int) ((long) getValue(false, mem,
op1) & 0xFFffFFff - 1));
break;
case VM_JMP:
setIP(getValue(false, mem, op1));
continue;
case VM_XOR: {
int result = getValue(cmd.isByteMode(), mem, op1)
^ getValue(cmd.isByteMode(), mem, op2);
flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result
& VMFlags.VM_FS.getFlag();
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
case VM_AND: {
int result = getValue(cmd.isByteMode(), mem, op1)
& getValue(cmd.isByteMode(), mem, op2);
flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result
& VMFlags.VM_FS.getFlag();
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
case VM_OR: {
int result = getValue(cmd.isByteMode(), mem, op1)
| getValue(cmd.isByteMode(), mem, op2);
flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result
& VMFlags.VM_FS.getFlag();
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
case VM_TEST: {
int result = getValue(cmd.isByteMode(), mem, op1)
& getValue(cmd.isByteMode(), mem, op2);
flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result
& VMFlags.VM_FS.getFlag();
}
break;
case VM_JS:
if ((flags & VMFlags.VM_FS.getFlag()) != 0) {
setIP(getValue(false, mem, op1));
continue;
}
break;
case VM_JNS:
if ((flags & VMFlags.VM_FS.getFlag()) == 0) {
setIP(getValue(false, mem, op1));
continue;
}
break;
case VM_JB:
if ((flags & VMFlags.VM_FC.getFlag()) != 0) {
setIP(getValue(false, mem, op1));
continue;
}
break;
case VM_JBE:
if ((flags & (VMFlags.VM_FC.getFlag() | VMFlags.VM_FZ.getFlag())) != 0) {
setIP(getValue(false, mem, op1));
continue;
}
break;
case VM_JA:
if ((flags & (VMFlags.VM_FC.getFlag() | VMFlags.VM_FZ.getFlag())) == 0) {
setIP(getValue(false, mem, op1));
continue;
}
break;
case VM_JAE:
if ((flags & VMFlags.VM_FC.getFlag()) == 0) {
setIP(getValue(false, mem, op1));
continue;
}
break;
case VM_PUSH:
R[7] -= 4;
setValue(false, mem, R[7] & VM_MEMMASK, getValue(false, mem,
op1));
break;
case VM_POP:
setValue(false, mem, op1, getValue(false, mem, R[7]
& VM_MEMMASK));
R[7] += 4;
break;
case VM_CALL:
R[7] -= 4;
setValue(false, mem, R[7] & VM_MEMMASK, IP + 1);
setIP(getValue(false, mem, op1));
continue;
case VM_NOT:
setValue(cmd.isByteMode(), mem, op1, ~getValue(
cmd.isByteMode(), mem, op1));
break;
case VM_SHL: {
int value1 = getValue(cmd.isByteMode(), mem, op1);
int value2 = getValue(cmd.isByteMode(), mem, op2);
int result = value1 << value2;
flags = (result == 0 ? VMFlags.VM_FZ.getFlag()
: (result & VMFlags.VM_FS.getFlag()))
| (((value1 << (value2 - 1)) & 0x80000000) != 0 ? VMFlags.VM_FC
.getFlag()
: 0);
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
case VM_SHR: {
int value1 = getValue(cmd.isByteMode(), mem, op1);
int value2 = getValue(cmd.isByteMode(), mem, op2);
int result = value1 >>> value2;
flags = (result == 0 ? VMFlags.VM_FZ.getFlag()
: (result & VMFlags.VM_FS.getFlag()))
| ((value1 >>> (value2 - 1)) & VMFlags.VM_FC.getFlag());
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
case VM_SAR: {
int value1 = getValue(cmd.isByteMode(), mem, op1);
int value2 = getValue(cmd.isByteMode(), mem, op2);
int result = ((int) value1) >> value2;
flags = (result == 0 ? VMFlags.VM_FZ.getFlag()
: (result & VMFlags.VM_FS.getFlag()))
| ((value1 >> (value2 - 1)) & VMFlags.VM_FC.getFlag());
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
case VM_NEG: {
int result = -getValue(cmd.isByteMode(), mem, op1);
flags = result == 0 ? VMFlags.VM_FZ.getFlag() : VMFlags.VM_FC
.getFlag()
| (result & VMFlags.VM_FS.getFlag());
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
case VM_NEGB:
setValue(true, mem, op1, -getValue(true, mem, op1));
break;
case VM_NEGD:
setValue(false, mem, op1, -getValue(false, mem, op1));
break;
case VM_PUSHA: {
for (int i = 0, SP = R[7] - 4; i < regCount; i++, SP -= 4) {
setValue(false, mem, SP & VM_MEMMASK, R[i]);
}
R[7] -= regCount * 4;
}
break;
case VM_POPA: {
for (int i = 0, SP = R[7]; i < regCount; i++, SP += 4)
R[7 - i] = getValue(false, mem, SP & VM_MEMMASK);
}
break;
case VM_PUSHF:
R[7] -= 4;
setValue(false, mem, R[7] & VM_MEMMASK, flags);
break;
case VM_POPF:
flags = getValue(false, mem, R[7] & VM_MEMMASK);
R[7] += 4;
break;
case VM_MOVZX:
setValue(false, mem, op1, getValue(true, mem, op2));
break;
case VM_MOVSX:
setValue(false, mem, op1, (byte) getValue(true, mem, op2));
break;
case VM_XCHG: {
int value1 = getValue(cmd.isByteMode(), mem, op1);
setValue(cmd.isByteMode(), mem, op1, getValue(cmd.isByteMode(),
mem, op2));
setValue(cmd.isByteMode(), mem, op2, value1);
}
break;
case VM_MUL: {
int result = (int) (((long) getValue(cmd.isByteMode(), mem, op1)
& 0xFFffFFff
* (long) getValue(cmd.isByteMode(), mem, op2) & 0xFFffFFff) & 0xFFffFFff);
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
case VM_DIV: {
int divider = getValue(cmd.isByteMode(), mem, op2);
if (divider != 0) {
int result = getValue(cmd.isByteMode(), mem, op1) / divider;
setValue(cmd.isByteMode(), mem, op1, result);
}
}
break;
case VM_ADC: {
int value1 = getValue(cmd.isByteMode(), mem, op1);
int FC = (flags & VMFlags.VM_FC.getFlag());
int result = (int) ((long) value1 & 0xFFffFFff
+ (long) getValue(cmd.isByteMode(), mem, op2)
& 0xFFffFFff + (long) FC & 0xFFffFFff);
if (cmd.isByteMode()) {
result &= 0xff;
}
flags = (result < value1 || result == value1 && FC != 0) ? 1
: 0 | (result == 0 ? VMFlags.VM_FZ.getFlag()
: (result & VMFlags.VM_FS.getFlag()));
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
case VM_SBB: {
int value1 = getValue(cmd.isByteMode(), mem, op1);
int FC = (flags & VMFlags.VM_FC.getFlag());
int result = (int) ((long) value1 & 0xFFffFFff
- (long) getValue(cmd.isByteMode(), mem, op2)
& 0xFFffFFff - (long) FC & 0xFFffFFff);
if (cmd.isByteMode()) {
result &= 0xff;
}
flags = (result > value1 || result == value1 && FC != 0) ? 1
: 0 | (result == 0 ? VMFlags.VM_FZ.getFlag()
: (result & VMFlags.VM_FS.getFlag()));
setValue(cmd.isByteMode(), mem, op1, result);
}
break;
case VM_RET:
if (R[7] >= VM_MEMSIZE) {
return (true);
}
setIP(getValue(false, mem, R[7] & VM_MEMMASK));
R[7] += 4;
continue;
case VM_STANDARD:
ExecuteStandardFilter(VMStandardFilters.findFilter(cmd.getOp1()
.getData()));
break;
case VM_PRINT:
break;
}
IP++;
--maxOpCount;
}
}
public void prepare(byte[] code, int codeSize, VMPreparedProgram prg) {
InitBitInput();
int cpLength = Math.min(MAX_SIZE, codeSize);
for (int i = 0; i < cpLength; i++) // memcpy(inBuf,Code,Min(CodeSize,BitInput::MAX_SIZE));
{
inBuf[i] |= code[i];
}
byte xorSum = 0;
for (int i = 1; i < codeSize; i++) {
xorSum ^= code[i];
}
faddbits(8);
prg.setCmdCount(0);
if (xorSum == code[0]) {
VMStandardFilters filterType = IsStandardFilter(code, codeSize);
if (filterType != VMStandardFilters.VMSF_NONE) {
VMPreparedCommand curCmd = new VMPreparedCommand();
curCmd.setOpCode(VMCommands.VM_STANDARD);
curCmd.getOp1().setData(filterType.getFilter());
curCmd.getOp1().setType(VMOpType.VM_OPNONE);
curCmd.getOp2().setType(VMOpType.VM_OPNONE);
codeSize = 0;
prg.getCmd().add(curCmd);
prg.setCmdCount(prg.getCmdCount()+1);
// TODO
// curCmd->Op1.Data=FilterType;
// >>>>>> CurCmd->Op1.Addr=&CurCmd->Op1.Data; <<<<<<<<<< not set
// do i need to ?
// >>>>>> CurCmd->Op2.Addr=&CurCmd->Op2.Data; <<<<<<<<<< "
// CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE;
// CodeSize=0;
}
int dataFlag = fgetbits();
faddbits(1);
// Read static data contained in DB operators. This data cannot be
// changed,
// it is a part of VM code, not a filter parameter.
if ((dataFlag & 0x8000) != 0) {
long dataSize = (long) ((long) ReadData(this) & 0xffFFffFF + 1);
for (int i = 0; inAddr < codeSize && i < dataSize; i++) {
prg.getStaticData().add(
Byte.valueOf((byte) (fgetbits() >> 8)));
faddbits(8);
}
}
while (inAddr < codeSize) {
VMPreparedCommand curCmd = new VMPreparedCommand();
int data = fgetbits();
if ((data & 0x8000) == 0) {
curCmd.setOpCode(VMCommands.findVMCommand((data >> 12)));
faddbits(4);
} else {
curCmd.setOpCode(VMCommands
.findVMCommand((data >> 10) - 24));
faddbits(6);
}
if ((VMCmdFlags.VM_CmdFlags[curCmd.getOpCode().getVMCommand()] & VMCmdFlags.VMCF_BYTEMODE) != 0) {
curCmd.setByteMode((fgetbits() >> 15) == 1 ? true : false);
faddbits(1);
} else {
curCmd.setByteMode(false);
}
curCmd.getOp1().setType(VMOpType.VM_OPNONE);
curCmd.getOp2().setType(VMOpType.VM_OPNONE);
int opNum = (VMCmdFlags.VM_CmdFlags[curCmd.getOpCode()
.getVMCommand()] & VMCmdFlags.VMCF_OPMASK);
// TODO >>> CurCmd->Op1.Addr=CurCmd->Op2.Addr=NULL; <<??
if (opNum > 0) {
decodeArg(curCmd.getOp1(), curCmd.isByteMode());
if (opNum == 2)
decodeArg(curCmd.getOp2(), curCmd.isByteMode());
else {
if (curCmd.getOp1().getType() == VMOpType.VM_OPINT
&& (VMCmdFlags.VM_CmdFlags[curCmd.getOpCode()
.getVMCommand()] & (VMCmdFlags.VMCF_JUMP | VMCmdFlags.VMCF_PROC)) != 0) {
int distance = curCmd.getOp1().getData();
if (distance >= 256)
distance -= 256;
else {
if (distance >= 136) {
distance -= 264;
} else {
if (distance >= 16) {
distance -= 8;
} else {
if (distance >= 8) {
distance -= 16;
}
}
}
distance += prg.getCmdCount();
}
curCmd.getOp1().setData(distance);
}
}
}
prg.setCmdCount(prg.getCmdCount() + 1);
prg.getCmd().add(curCmd);
}
}
VMPreparedCommand curCmd = new VMPreparedCommand();
curCmd.setOpCode(VMCommands.VM_RET);
// TODO CurCmd->Op1.Addr=&CurCmd->Op1.Data;
// CurCmd->Op2.Addr=&CurCmd->Op2.Data;
curCmd.getOp1().setType(VMOpType.VM_OPNONE);
curCmd.getOp2().setType(VMOpType.VM_OPNONE);
// for (int i=0;iCmd[I];
// if (Cmd->Op1.Addr==NULL)
// Cmd->Op1.Addr=&Cmd->Op1.Data;
// if (Cmd->Op2.Addr==NULL)
// Cmd->Op2.Addr=&Cmd->Op2.Data;
// }
prg.getCmd().add(curCmd);
prg.setCmdCount(prg.getCmdCount()+1);
// #ifdef VM_OPTIMIZE
if (codeSize != 0) {
optimize(prg);
}
}
private void decodeArg(VMPreparedOperand op, boolean byteMode) {
int data = fgetbits();
if ((data & 0x8000) != 0) {
op.setType(VMOpType.VM_OPREG);
op.setData((data >> 12) & 7);
op.setOffset(op.getData());
faddbits(4);
} else {
if ((data & 0xc000) == 0) {
op.setType(VMOpType.VM_OPINT);
if (byteMode) {
op.setData((data >> 6) & 0xff);
faddbits(10);
} else {
faddbits(2);
op.setData(ReadData(this));
}
} else {
op.setType(VMOpType.VM_OPREGMEM);
if ((data & 0x2000) == 0) {
op.setData((data >> 10) & 7);
op.setOffset(op.getData());
op.setBase(0);
faddbits(6);
} else {
if ((data & 0x1000) == 0) {
op.setData((data >> 9) & 7);
op.setOffset(op.getData());
faddbits(7);
} else {
op.setData(0);
faddbits(4);
}
op.setBase(ReadData(this));
}
}
}
}
private void optimize(VMPreparedProgram prg) {
List commands = prg.getCmd();
for (VMPreparedCommand cmd : commands) {
switch (cmd.getOpCode()) {
case VM_MOV:
cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_MOVB
: VMCommands.VM_MOVD);
continue;
case VM_CMP:
cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_CMPB
: VMCommands.VM_CMPD);
continue;
}
if ((VMCmdFlags.VM_CmdFlags[cmd.getOpCode().getVMCommand()] & VMCmdFlags.VMCF_CHFLAGS) == 0) {
continue;
}
boolean flagsRequired = false;
for (int i = commands.indexOf(cmd) + 1; i < commands.size(); i++) {
int flags = VMCmdFlags.VM_CmdFlags[commands.get(i).getOpCode()
.getVMCommand()];
if ((flags & (VMCmdFlags.VMCF_JUMP | VMCmdFlags.VMCF_PROC | VMCmdFlags.VMCF_USEFLAGS)) != 0) {
flagsRequired = true;
break;
}
if ((flags & VMCmdFlags.VMCF_CHFLAGS) != 0) {
break;
}
}
if (flagsRequired) {
continue;
}
switch (cmd.getOpCode()) {
case VM_ADD:
cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_ADDB
: VMCommands.VM_ADDD);
continue;
case VM_SUB:
cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_SUBB
: VMCommands.VM_SUBD);
continue;
case VM_INC:
cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_INCB
: VMCommands.VM_INCD);
continue;
case VM_DEC:
cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_DECB
: VMCommands.VM_DECD);
continue;
case VM_NEG:
cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_NEGB
: VMCommands.VM_NEGD);
continue;
}
}
}
public static int ReadData(BitInput rarVM) {
int data = rarVM.fgetbits();
switch (data & 0xc000) {
case 0:
rarVM.faddbits(6);
return ((data >> 10) & 0xf);
case 0x4000:
if ((data & 0x3c00) == 0) {
data = 0xffffff00 | ((data >> 2) & 0xff);
rarVM.faddbits(14);
} else {
data = (data >> 6) & 0xff;
rarVM.faddbits(10);
}
return (data);
case 0x8000:
rarVM.faddbits(2);
data = rarVM.fgetbits();
rarVM.faddbits(16);
return (data);
default:
rarVM.faddbits(2);
data = (rarVM.fgetbits() << 16);
rarVM.faddbits(16);
data |= rarVM.fgetbits();
rarVM.faddbits(16);
return (data);
}
}
private VMStandardFilters IsStandardFilter(byte[] code, int codeSize) {
VMStandardFilterSignature stdList[]={
new VMStandardFilterSignature(53, 0xad576887, VMStandardFilters.VMSF_E8),
new VMStandardFilterSignature(57, 0x3cd7e57e, VMStandardFilters.VMSF_E8E9),
new VMStandardFilterSignature(120, 0x3769893f, VMStandardFilters.VMSF_ITANIUM),
new VMStandardFilterSignature(29, 0x0e06077d, VMStandardFilters.VMSF_DELTA),
new VMStandardFilterSignature(149, 0x1c2c5dc8, VMStandardFilters.VMSF_RGB),
new VMStandardFilterSignature(216, 0xbc85e701, VMStandardFilters.VMSF_AUDIO),
new VMStandardFilterSignature(40, 0x46b9c560, VMStandardFilters.VMSF_UPCASE)
};
int CodeCRC = RarCRC.checkCrc(0xffffffff,code,0,code.length)^0xffffffff;
for (int i=0;i=VM_GLOBALMEMADDR){
break;
}
int fileSize=0x1000000;
byte cmpByte2=(byte) ((filterType==VMStandardFilters.VMSF_E8E9) ? 0xe9:0xe8);
for (int curPos=0;curPos=0)
// SET_VALUE(false,Data,Addr+FileSize);
// }
// else
// if (Addr=VM_GLOBALMEMADDR){
break;
}
int curPos=0;
final byte Masks[]={4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
fileOffset>>>=4;
while (curPos=0)
{
byte cmdMask=Masks[Byte];
if (cmdMask!=0)
for (int i=0;i<=2;i++)
if ((cmdMask & (1<=VM_GLOBALMEMADDR/2){
break;
}
// bytes from same channels are grouped to continual data blocks,
// so we need to place them back to their interleaving positions
for (int curChannel=0;curChannel=VM_GLOBALMEMADDR/2 || posR<0){
break;
}
for (int curChannel=0;curChannel=3)
{
int upperDataPos=destDataPos+upperPos;
int upperByte=mem[(int)upperDataPos]&0xff;
int upperLeftByte=mem[upperDataPos-3]&0xff;
predicted=prevByte+upperByte-upperLeftByte;
int pa=Math.abs((int)(predicted-prevByte));
int pb=Math.abs((int)(predicted-upperByte));
int pc=Math.abs((int)(predicted-upperLeftByte));
if (pa<=pb && pa<=pc){
predicted=prevByte;
}
else{
if (pb<=pc){
predicted=upperByte;
}
else{
predicted=upperLeftByte;
}
}
}
else{
predicted=prevByte;
}
prevByte=(predicted-mem[srcPos++]&0xff)&0xff;
mem[destDataPos+i]=(byte)(prevByte&0xff);
}
}
for (int i=posR,border=dataSize-2;i=VM_GLOBALMEMADDR/2){
break;
}
for (int curChannel=0;curChannel>>3) & 0xff;
long curByte=mem[srcPos++]&0xff;
predicted = (predicted - curByte)&UINT_MASK;
mem[destDataPos+i]=(byte)predicted;
prevDelta=(byte)(predicted-prevByte);
prevByte=predicted;
int D=((byte)curByte)<<3;
Dif[0]+=Math.abs(D);
Dif[1]+=Math.abs(D-D1);
Dif[2]+=Math.abs(D+D1);
Dif[3]+=Math.abs(D-D2);
Dif[4]+=Math.abs(D+D2);
Dif[5]+=Math.abs(D-D3);
Dif[6]+=Math.abs(D+D3);
if ((byteCount & 0x1f)==0)
{
long minDif=Dif[0], numMinDif=0;
Dif[0]=0;
for (int j=1;j=-16) K1--; break;
case 2: if (K1 < 16) K1++; break;
case 3: if (K2>=-16) K2--; break;
case 4: if (K2 < 16) K2++; break;
case 5: if (K3>=-16) K3--; break;
case 6: if (K3 < 16) K3++; break;
}
}
}
}
}
break;
case VMSF_UPCASE:
{
int dataSize=R[4],srcPos=0,destPos=dataSize;
if (dataSize>=VM_GLOBALMEMADDR/2){
break;
}
while (srcPos>>(32-bitCount);
andMask=~(andMask<>>8)|0xff000000;
bitField>>>=8;
}
}
private int filterItanium_GetBits(int curPos, int bitPos, int bitCount) {
int inAddr=bitPos/8;
int inBit=bitPos&7;
int bitField=(int)(mem[curPos+inAddr++]&0xff);
bitField|=(int) ((mem[curPos+inAddr++]&0xff) << 8);
bitField|=(int) ((mem[curPos+inAddr++]&0xff) << 16);
bitField|=(int) ((mem[curPos+inAddr]&0xff) << 24);
bitField >>>= inBit;
return(bitField & (0xffffffff>>>(32-bitCount)));
}
public void setMemory(int pos,byte[] data,int offset,int dataSize)
{
if (pos": ">" or ">"
* "@": "@"
*/
package com.github.junrar.unpack.vm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class VMCmdFlags {
public static final byte VMCF_OP0 = 0;
public static final byte VMCF_OP1 = 1;
public static final byte VMCF_OP2 = 2;
public static final byte VMCF_OPMASK = 3;
public static final byte VMCF_BYTEMODE = 4;
public static final byte VMCF_JUMP = 8;
public static final byte VMCF_PROC = 16;
public static final byte VMCF_USEFLAGS = 32;
public static final byte VMCF_CHFLAGS = 64;
public static byte VM_CmdFlags[]=
{
/* VM_MOV */ VMCF_OP2 | VMCF_BYTEMODE ,
/* VM_CMP */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_ADD */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_SUB */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_JZ */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
/* VM_JNZ */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
/* VM_INC */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_DEC */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_JMP */ VMCF_OP1 | VMCF_JUMP ,
/* VM_XOR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_AND */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_OR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_TEST */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_JS */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
/* VM_JNS */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
/* VM_JB */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
/* VM_JBE */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
/* VM_JA */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
/* VM_JAE */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS ,
/* VM_PUSH */ VMCF_OP1 ,
/* VM_POP */ VMCF_OP1 ,
/* VM_CALL */ VMCF_OP1 | VMCF_PROC ,
/* VM_RET */ VMCF_OP0 | VMCF_PROC ,
/* VM_NOT */ VMCF_OP1 | VMCF_BYTEMODE ,
/* VM_SHL */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_SHR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_SAR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_NEG */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS ,
/* VM_PUSHA */ VMCF_OP0 ,
/* VM_POPA */ VMCF_OP0 ,
/* VM_PUSHF */ VMCF_OP0 | VMCF_USEFLAGS ,
/* VM_POPF */ VMCF_OP0 | VMCF_CHFLAGS ,
/* VM_MOVZX */ VMCF_OP2 ,
/* VM_MOVSX */ VMCF_OP2 ,
/* VM_XCHG */ VMCF_OP2 | VMCF_BYTEMODE ,
/* VM_MUL */ VMCF_OP2 | VMCF_BYTEMODE ,
/* VM_DIV */ VMCF_OP2 | VMCF_BYTEMODE ,
/* VM_ADC */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS ,
/* VM_SBB */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS ,
/* VM_PRINT */ VMCF_OP0
};
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/vm/VMCommands.java
================================================
/*
* 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.vm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public enum VMCommands {
VM_MOV(0), VM_CMP(1), VM_ADD(2), VM_SUB(3), VM_JZ(4), VM_JNZ(5), VM_INC(6), VM_DEC(
7), VM_JMP(8), VM_XOR(9), VM_AND(10), VM_OR(11), VM_TEST(12), VM_JS(
13), VM_JNS(14), VM_JB(15), VM_JBE(16), VM_JA(17), VM_JAE(18), VM_PUSH(
19), VM_POP(20), VM_CALL(21), VM_RET(22), VM_NOT(23), VM_SHL(24), VM_SHR(
25), VM_SAR(26), VM_NEG(27), VM_PUSHA(28), VM_POPA(29), VM_PUSHF(30), VM_POPF(
31), VM_MOVZX(32), VM_MOVSX(33), VM_XCHG(34), VM_MUL(35), VM_DIV(36), VM_ADC(
37), VM_SBB(38), VM_PRINT(39),
// #ifdef VM_OPTIMIZE
VM_MOVB(40), VM_MOVD(41), VM_CMPB(42), VM_CMPD(43),
VM_ADDB(44), VM_ADDD(45), VM_SUBB(46), VM_SUBD(47), VM_INCB(48), VM_INCD(49), VM_DECB(
50), VM_DECD(51), VM_NEGB(52), VM_NEGD(53),
// #endif*/
VM_STANDARD(54);
private int vmCommand;
private VMCommands(int vmCommand) {
this.vmCommand = vmCommand;
}
public int getVMCommand() {
return vmCommand;
}
public boolean equals(int vmCommand) {
return this.vmCommand == vmCommand;
}
public static VMCommands findVMCommand(int vmCommand) {
if (VM_MOV.equals(vmCommand)) {
return VM_MOV;
}
if (VM_CMP.equals(vmCommand)) {
return VM_CMP;
}
if (VM_ADD.equals(vmCommand)) {
return VM_ADD;
}
if (VM_SUB.equals(vmCommand)) {
return VM_SUB;
}
if (VM_JZ.equals(vmCommand)) {
return VM_JZ;
}
if (VM_JNZ.equals(vmCommand)) {
return VM_JNZ;
}
if (VM_INC.equals(vmCommand)) {
return VM_INC;
}
if (VM_DEC.equals(vmCommand)) {
return VM_DEC;
}
if (VM_JMP.equals(vmCommand)) {
return VM_JMP;
}
if (VM_XOR.equals(vmCommand)) {
return VM_XOR;
}
if (VM_AND.equals(vmCommand)) {
return VM_AND;
}
if (VM_OR.equals(vmCommand)) {
return VM_OR;
}
if (VM_TEST.equals(vmCommand)) {
return VM_TEST;
}
if (VM_JS.equals(vmCommand)) {
return VM_JS;
}
if (VM_JNS.equals(vmCommand)) {
return VM_JNS;
}
if (VM_JB.equals(vmCommand)) {
return VM_JB;
}
if (VM_JBE.equals(vmCommand)) {
return VM_JBE;
}
if (VM_JA.equals(vmCommand)) {
return VM_JA;
}
if (VM_JAE.equals(vmCommand)) {
return VM_JAE;
}
if (VM_PUSH.equals(vmCommand)) {
return VM_PUSH;
}
if (VM_POP.equals(vmCommand)) {
return VM_POP;
}
if (VM_CALL.equals(vmCommand)) {
return VM_CALL;
}
if (VM_RET.equals(vmCommand)) {
return VM_RET;
}
if (VM_NOT.equals(vmCommand)) {
return VM_NOT;
}
if (VM_SHL.equals(vmCommand)) {
return VM_SHL;
}
if (VM_SHR.equals(vmCommand)) {
return VM_SHR;
}
if (VM_SAR.equals(vmCommand)) {
return VM_SAR;
}
if (VM_NEG.equals(vmCommand)) {
return VM_NEG;
}
if (VM_PUSHA.equals(vmCommand)) {
return VM_PUSHA;
}
if (VM_POPA.equals(vmCommand)) {
return VM_POPA;
}
if (VM_PUSHF.equals(vmCommand)) {
return VM_PUSHF;
}
if (VM_POPF.equals(vmCommand)) {
return VM_POPF;
}
if (VM_MOVZX.equals(vmCommand)) {
return VM_MOVZX;
}
if (VM_MOVSX.equals(vmCommand)) {
return VM_MOVSX;
}
if (VM_XCHG.equals(vmCommand)) {
return VM_XCHG;
}
if (VM_MUL.equals(vmCommand)) {
return VM_MUL;
}
if (VM_DIV.equals(vmCommand)) {
return VM_DIV;
}
if (VM_ADC.equals(vmCommand)) {
return VM_ADC;
}
if (VM_SBB.equals(vmCommand)) {
return VM_SBB;
}
if (VM_PRINT.equals(vmCommand)) {
return VM_PRINT;
}
if (VM_MOVB.equals(vmCommand)) {
return VM_MOVB;
}
if (VM_MOVD.equals(vmCommand)) {
return VM_MOVD;
}
if (VM_CMPB.equals(vmCommand)) {
return VM_CMPB;
}
if (VM_CMPD.equals(vmCommand)) {
return VM_CMPD;
}
if (VM_ADDB.equals(vmCommand)) {
return VM_ADDB;
}
if (VM_ADDD.equals(vmCommand)) {
return VM_ADDD;
}
if (VM_SUBB.equals(vmCommand)) {
return VM_SUBB;
}
if (VM_SUBD.equals(vmCommand)) {
return VM_SUBD;
}
if (VM_INCB.equals(vmCommand)) {
return VM_INCB;
}
if (VM_INCD.equals(vmCommand)) {
return VM_INCD;
}
if (VM_DECB.equals(vmCommand)) {
return VM_DECB;
}
if (VM_DECD.equals(vmCommand)) {
return VM_DECD;
}
if (VM_NEGB.equals(vmCommand)) {
return VM_NEGB;
}
if (VM_NEGD.equals(vmCommand)) {
return VM_NEGD;
}
if (VM_STANDARD.equals(vmCommand)) {
return VM_STANDARD;
}
return null;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/vm/VMFlags.java
================================================
/*
* 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.vm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public enum VMFlags {
/**
*
*/
VM_FC (1),
/**
*
*/
VM_FZ (2),
/**
*
*/
VM_FS (0x80000000);
private int flag;
private VMFlags(int flag){
this.flag = flag;
}
/**
* Returns the VMFlags Type of the given int or null
* @param flag as int
* @return VMFlag of the int value
*/
public static VMFlags findFlag(int flag){
if(VM_FC.equals(flag)){
return VM_FC;
}
if(VM_FS.equals(flag)){
return VM_FS;
}
if(VM_FZ.equals(flag)){
return VM_FZ;
}
return null;
}
/**
* Returns true if the flag provided as int is equal to the enum
* @param flag
* @return returns true if the flag is equal to the enum
*/
public boolean equals(int flag){
return this.flag == flag;
}
/**
* @return the flag as int
*/
public int getFlag() {
return flag;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/vm/VMOpType.java
================================================
/*
* 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.vm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public enum VMOpType {
VM_OPREG (0),
VM_OPINT (1),
VM_OPREGMEM (2),
VM_OPNONE (3);
private int opType;
private VMOpType(int opType){
this.opType=opType;
}
public int getOpType() {
return opType;
}
public boolean equals(int opType){
return this.opType == opType;
}
public static VMOpType findOpType(int opType){
if (VM_OPREG.equals(opType)) {
return VM_OPREG;
}
if (VM_OPINT.equals(opType)) {
return VM_OPINT;
}
if (VM_OPREGMEM.equals(opType)) {
return VM_OPREGMEM;
}
if (VM_OPNONE.equals(opType)) {
return VM_OPNONE;
}
return null;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/vm/VMPreparedCommand.java
================================================
/*
* 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.vm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class VMPreparedCommand {
private VMCommands OpCode;
private boolean ByteMode;
private VMPreparedOperand Op1 = new VMPreparedOperand();
private VMPreparedOperand Op2 = new VMPreparedOperand();
public boolean isByteMode() {
return ByteMode;
}
public void setByteMode(boolean byteMode) {
ByteMode = byteMode;
}
public VMPreparedOperand getOp1() {
return Op1;
}
public void setOp1(VMPreparedOperand op1) {
Op1 = op1;
}
public VMPreparedOperand getOp2() {
return Op2;
}
public void setOp2(VMPreparedOperand op2) {
Op2 = op2;
}
public VMCommands getOpCode() {
return OpCode;
}
public void setOpCode(VMCommands opCode) {
OpCode = opCode;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/vm/VMPreparedOperand.java
================================================
/*
* 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.vm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class VMPreparedOperand {
private VMOpType Type;
private int Data;
private int Base;
private int offset;
public int getBase() {
return Base;
}
public void setBase(int base) {
Base = base;
}
public int getData() {
return Data;
}
public void setData(int data) {
Data = data;
}
public VMOpType getType() {
return Type;
}
public void setType(VMOpType type) {
Type = type;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/vm/VMPreparedProgram.java
================================================
/*
* 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.vm;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class VMPreparedProgram
{
private List Cmd = new ArrayList();
private List AltCmd =new ArrayList();
private int CmdCount;
private Vector GlobalData = new Vector();
private Vector StaticData = new Vector(); // static data contained in DB operators
private int InitR[] = new int[7];
private int FilteredDataOffset;
private int FilteredDataSize;
public VMPreparedProgram()
{
AltCmd=null;
}
public List getAltCmd() {
return AltCmd;
}
public void setAltCmd(List altCmd) {
AltCmd = altCmd;
}
public List getCmd() {
return Cmd;
}
public void setCmd(List cmd) {
Cmd = cmd;
}
public int getCmdCount() {
return CmdCount;
}
public void setCmdCount(int cmdCount) {
CmdCount = cmdCount;
}
public int getFilteredDataOffset() {
return FilteredDataOffset;
}
public void setFilteredDataOffset(int filteredDataOffset) {
FilteredDataOffset = filteredDataOffset;
}
public int getFilteredDataSize() {
return FilteredDataSize;
}
public void setFilteredDataSize(int filteredDataSize) {
FilteredDataSize = filteredDataSize;
}
public Vector getGlobalData() {
return GlobalData;
}
public void setGlobalData(Vector globalData) {
GlobalData = globalData;
}
public int[] getInitR() {
return InitR;
}
public void setInitR(int[] initR) {
InitR = initR;
}
public Vector getStaticData() {
return StaticData;
}
public void setStaticData(Vector staticData) {
StaticData = staticData;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/vm/VMStandardFilterSignature.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 04.06.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.vm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class VMStandardFilterSignature {
private int length;
private int CRC;
private VMStandardFilters type;
public VMStandardFilterSignature(int length, int crc, VMStandardFilters type) {
super();
this.length = length;
CRC = crc;
this.type = type;
}
public int getCRC() {
return CRC;
}
public void setCRC(int crc) {
CRC = crc;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public VMStandardFilters getType() {
return type;
}
public void setType(VMStandardFilters type) {
this.type = type;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unpack/vm/VMStandardFilters.java
================================================
/*
* 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.vm;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public enum VMStandardFilters {
VMSF_NONE ((int)0),
VMSF_E8 ((int)1),
VMSF_E8E9 ((int)2),
VMSF_ITANIUM( (int)3),
VMSF_RGB ((int)4),
VMSF_AUDIO ((int)5),
VMSF_DELTA ((int)6),
VMSF_UPCASE ((int)7);
private int filter;
private VMStandardFilters(int filter){
this.filter=filter;
}
public int getFilter() {
return filter;
}
public boolean equals(int filter){
return this.filter == filter;
}
public static VMStandardFilters findFilter(int filter){
if (VMSF_NONE.equals(filter)) {
return VMSF_NONE;
}
if (VMSF_E8.equals(filter)) {
return VMSF_E8;
}
if (VMSF_E8E9.equals(filter)) {
return VMSF_E8E9;
}
if (VMSF_ITANIUM.equals(filter)) {
return VMSF_ITANIUM;
}
if (VMSF_RGB.equals(filter)) {
return VMSF_RGB;
}
if (VMSF_AUDIO.equals(filter)) {
return VMSF_AUDIO;
}
if (VMSF_DELTA.equals(filter)) {
return VMSF_DELTA;
}
return null;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unsigned/UnsignedByte.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 04.06.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.unsigned;
import com.github.junrar.crc.RarCRC;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class UnsignedByte {
public static byte longToByte(long unsignedByte1){
return (byte) (unsignedByte1&0xff);
}
public static byte intToByte(int unsignedByte1){
return (byte) (unsignedByte1&0xff);
}
public static byte shortToByte(short unsignedByte1){
return (byte) (unsignedByte1&0xff);
}
public static short add(byte unsignedByte1, byte unsignedByte2){
return (short) (unsignedByte1 + unsignedByte2);
}
public static short sub(byte unsignedByte1, byte unsignedByte2){
return (short) (unsignedByte1 - unsignedByte2);
}
public static void main(String[] args)
{
//tests unsigned (signed)
//add
System.out.println(add((byte)0xfe,(byte)0x01)); //255 (-1)
System.out.println(add((byte)0xff,(byte)0x01)); //0 (0)
System.out.println(add((byte)0x7f,(byte)0x01)); //128 (-128)
System.out.println(add((byte)0xff,(byte)0xff)); //254 (-2)
//sub
System.out.println(sub((byte)0xfe,(byte)0x01)); //253 (-3)
System.out.println(sub((byte)0x00,(byte)0x01)); //255 (-1)
System.out.println(sub((byte)0x80,(byte)0x01)); //127 (127)
//mul
System.out.println((byte)-1*(byte)-1);
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unsigned/UnsignedInteger.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 04.06.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.unsigned;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class UnsignedInteger {
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unsigned/UnsignedLong.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 04.06.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.unsigned;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class UnsignedLong {
}
================================================
FILE: unrar/src/main/java/com/github/junrar/unsigned/UnsignedShort.java
================================================
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 04.06.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.unsigned;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public class UnsignedShort {
}
================================================
FILE: unrar/src/main/java/com/github/junrar/util/VolumeHelper.java
================================================
package com.github.junrar.util;
/**
*
* @author alban
*/
public class VolumeHelper {
private VolumeHelper() {
}
// public static boolean mergeArchive(Archive archive, ComprDataIO dataIO)
// throws IOException {
// FileHeader hd = dataIO.getSubHeader();
// if (hd.getUnpVersion() >= 20 && hd.getFileCRC() != 0xffffffff
// && dataIO.getPackedCRC() != ~hd.getFileCRC()) {
// System.err.println("Data Bad CRC");
// }
//
// boolean oldNumbering = !archive.getMainHeader().isNewNumbering()
// || archive.isOldFormat();
// String nextName = nextVolumeName(archive.getFile().getAbsolutePath(),
// oldNumbering);
// File nextVolume = new File(nextName);
// UnrarCallback callback = archive.getUnrarCallback();
// if ((callback != null) && !callback.isNextVolumeReady(nextVolume)) {
// return false;
// }
// if (!nextVolume.exists()) {
// return false;
// }
// archive.setFile(nextVolume);
// hd = archive.nextFileHeader();
// if (hd == null) {
// return false;
// }
// dataIO.init(hd);
// return true;
// }
public static String nextVolumeName(String arcName, boolean oldNumbering) {
if (!oldNumbering) {
// part1.rar, part2.rar, ...
int len = arcName.length();
int indexR = len - 1;
while ((indexR >= 0) && !isDigit(arcName.charAt(indexR))) {
indexR--;
}
int index = indexR + 1;
int indexL = indexR - 1;
while ((indexL >= 0) && isDigit(arcName.charAt(indexL))) {
indexL--;
}
if (indexL < 0) {
return null;
}
indexL++;
StringBuilder buffer = new StringBuilder(len);
buffer.append(arcName, 0, indexL);
char[] digits = new char[indexR - indexL + 1];
arcName.getChars(indexL, indexR + 1, digits, 0);
indexR = digits.length - 1;
while ((indexR >= 0) && (++digits[indexR]) == '9' + 1) {
digits[indexR] = '0';
indexR--;
}
if (indexR < 0) {
buffer.append('1');
}
buffer.append(digits);
buffer.append(arcName, index, len);
return buffer.toString();
} else {
// .rar, .r00, .r01, ...
int len = arcName.length();
if ((len <= 4) || (arcName.charAt(len - 4) != '.')) {
return null;
}
StringBuilder buffer = new StringBuilder();
int off = len - 3;
buffer.append(arcName, 0, off);
if (!isDigit(arcName.charAt(off + 1))
|| !isDigit(arcName.charAt(off + 2))) {
buffer.append("r00");
} else {
char[] ext = new char[3];
arcName.getChars(off, len, ext, 0);
int i = ext.length - 1;
while ((++ext[i]) == '9' + 1) {
ext[i] = '0';
i--;
}
buffer.append(ext);
}
return buffer.toString();
}
}
private static boolean isDigit(char c) {
return (c >= '0') && (c <= '9');
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/vfs2/provider/rar/RARFileObject.java
================================================
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 com.github.junrar.vfs2.provider.rar;
import java.io.InputStream;
import java.util.HashSet;
import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.provider.AbstractFileName;
import org.apache.commons.vfs2.provider.AbstractFileObject;
import com.github.junrar.Archive;
import com.github.junrar.rarfile.FileHeader;
/**
* A file in a RAR file system.
*
* @author Rogiel
*/
public class RARFileObject extends AbstractFileObject implements FileObject {
/**
* The TFile.
*/
protected Archive archive;
protected FileHeader header;
@SuppressWarnings("unused")
private final RARFileSystem fs;
private final HashSet children = new HashSet();
protected RARFileObject(AbstractFileName name, Archive archive,
FileHeader header, RARFileSystem fs) throws FileSystemException {
super(name, fs);
this.fs = fs;
this.archive = archive;
this.header = header;
archive.getMainHeader().isFirstVolume();
}
@Override
public boolean doIsWriteable() throws FileSystemException {
return false;
}
@Override
protected FileType doGetType() {
if (header == null || header.isDirectory()) {
return FileType.FOLDER;
} else {
return FileType.FILE;
}
}
@Override
protected String[] doListChildren() {
try {
if (!getType().hasChildren()) {
return null;
}
} catch (FileSystemException e) {
// should not happen as the type has already been cached.
throw new RuntimeException(e);
}
return children.toArray(new String[children.size()]);
}
@Override
protected long doGetContentSize() {
return header.getFullUnpackSize();
}
@Override
protected long doGetLastModifiedTime() throws Exception {
return header.getMTime().getTime();
}
@Override
protected InputStream doGetInputStream() throws Exception {
if (!getType().hasContent()) {
throw new FileSystemException("vfs.provider/read-not-file.error",
getName());
}
return archive.getInputStream(header);
}
/**
* Attaches a child.
*
* @param childName
* The name of the child.
*/
public void attachChild(FileName childName) {
children.add(childName.getBaseName());
}
/**
* @param header
*/
public void setHeader(FileHeader header) {
this.header = header;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/vfs2/provider/rar/RARFileProvider.java
================================================
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 com.github.junrar.vfs2.provider.rar;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import org.apache.commons.vfs2.Capability;
import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystem;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.provider.AbstractFileName;
import org.apache.commons.vfs2.provider.AbstractLayeredFileProvider;
import org.apache.commons.vfs2.provider.FileProvider;
import org.apache.commons.vfs2.provider.LayeredFileName;
/**
* A file system provider for RAR files. Provides read-only file systems.
*
* @author Rogiel
*/
public class RARFileProvider extends AbstractLayeredFileProvider implements
FileProvider {
/** The list of capabilities this provider supports */
protected static final Collection capabilities = Collections
.unmodifiableCollection(Arrays.asList(new Capability[] {
Capability.GET_LAST_MODIFIED,
Capability.GET_TYPE,
Capability.LIST_CHILDREN,
Capability.READ_CONTENT,
Capability.URI,
Capability.COMPRESS,
Capability.VIRTUAL
}));
public RARFileProvider() {
super();
}
/**
* Creates a layered file system. This method is called if the file system
* is not cached.
*
* @param scheme
* The URI scheme.
* @param file
* The file to create the file system on top of.
* @return The file system.
*/
@Override
protected FileSystem doCreateFileSystem(final String scheme,
final FileObject file, final FileSystemOptions fileSystemOptions)
throws FileSystemException {
final AbstractFileName rootName = new LayeredFileName(scheme,
file.getName(), FileName.ROOT_PATH, FileType.FOLDER);
return new RARFileSystem(rootName, file, fileSystemOptions);
}
public Collection getCapabilities() {
return capabilities;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/vfs2/provider/rar/RARFileSystem.java
================================================
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 com.github.junrar.vfs2.provider.rar;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.vfs2.Capability;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystem;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.provider.AbstractFileName;
import org.apache.commons.vfs2.provider.AbstractFileSystem;
import org.apache.commons.vfs2.provider.UriParser;
import com.github.junrar.Archive;
import com.github.junrar.exception.RarException;
import com.github.junrar.rarfile.FileHeader;
/**
* A read-only file system for RAR files.
*
* @author Rogiel
*/
public class RARFileSystem extends AbstractFileSystem implements FileSystem {
private final FileObject parentLayer;
private Archive archive;
private Map files = new HashMap();
public RARFileSystem(final AbstractFileName rootName,
final FileObject parentLayer,
final FileSystemOptions fileSystemOptions)
throws FileSystemException {
super(rootName, parentLayer, fileSystemOptions);
this.parentLayer = parentLayer;
}
@Override
public void init() throws FileSystemException {
super.init();
try {
try {
archive = new Archive(new VFSVolumeManager(parentLayer));
// Build the index
List strongRef = new ArrayList(
100);
for (final FileHeader header : archive.getFileHeaders()) {
AbstractFileName name = (AbstractFileName) getFileSystemManager()
.resolveName(
getRootName(),
UriParser.encode(header.getFileNameString()));
// Create the file
RARFileObject fileObj;
if (header.isDirectory() && getFileFromCache(name) != null) {
fileObj = (RARFileObject) getFileFromCache(name);
fileObj.setHeader(header);
continue;
}
fileObj = createRARFileObject(name, header);
putFileToCache(fileObj);
strongRef.add(fileObj);
fileObj.holdObject(strongRef);
// Make sure all ancestors exist
RARFileObject parent;
for (AbstractFileName parentName = (AbstractFileName) name
.getParent(); parentName != null; fileObj = parent, parentName = (AbstractFileName) parentName
.getParent()) {
// Locate the parent
parent = (RARFileObject) getFileFromCache(parentName);
if (parent == null) {
parent = createRARFileObject(parentName, null);
putFileToCache(parent);
strongRef.add(parent);
parent.holdObject(strongRef);
}
// Attach child to parent
parent.attachChild(fileObj.getName());
}
}
} catch (RarException e) {
throw new FileSystemException(e);
} catch (IOException e) {
throw new FileSystemException(e);
}
} finally {
// closeCommunicationLink();
}
}
protected RARFileObject createRARFileObject(final AbstractFileName name,
final FileHeader header) throws FileSystemException {
return new RARFileObject(name, archive, header, this);
}
@Override
protected void doCloseCommunicationLink() {
try {
archive.close();
} catch (FileSystemException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Returns the capabilities of this file system.
*/
@Override
protected void addCapabilities(final Collection caps) {
caps.addAll(RARFileProvider.capabilities);
}
/**
* Creates a file object.
*/
@Override
protected FileObject createFile(final AbstractFileName name)
throws FileSystemException {
String path = name.getPath().substring(1);
if (path.length() == 0) {
return new RARFileObject(name, archive, null, this);
} else if (files.containsKey(name.getPath())) {
return new RARFileObject(name, archive, files.get(name.getPath()),
this);
}
return null;
}
/**
* will be called after all file-objects closed their streams.
*/
protected void notifyAllStreamsClosed() {
closeCommunicationLink();
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/vfs2/provider/rar/RandomAccessContentAccess.java
================================================
/*
* This file is part of seedbox .
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see .
*/
package com.github.junrar.vfs2.provider.rar;
import java.io.IOException;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.RandomAccessContent;
import org.apache.commons.vfs2.util.RandomAccessMode;
import com.github.junrar.io.IReadOnlyAccess;
/**
* @author Rogiel
*
*/
public class RandomAccessContentAccess implements IReadOnlyAccess {
private final RandomAccessContent rac;
/**
* @param rac
*/
public RandomAccessContentAccess(RandomAccessContent rac) {
this.rac = rac;
}
/**
* @param rac
* @throws FileSystemException
*/
public RandomAccessContentAccess(FileObject file)
throws FileSystemException {
this(file.getContent().getRandomAccessContent(RandomAccessMode.READ));
}
public long getPosition() throws IOException {
return rac.getFilePointer();
}
public void setPosition(long pos) throws IOException {
rac.seek(pos);
}
public int read() throws IOException {
return rac.readByte();
}
public int read(byte[] buffer, int off, int count) throws IOException {
return rac.getInputStream().read(buffer, off, count);
}
public int readFully(byte[] buffer, int count) throws IOException {
return rac.getInputStream().read(buffer, 0, count);
}
public void close() throws IOException {
rac.close();
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/vfs2/provider/rar/VFSVolume.java
================================================
/*
* This file is part of seedbox .
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see .
*/
package com.github.junrar.vfs2.provider.rar;
import java.io.IOException;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.RandomAccessContent;
import org.apache.commons.vfs2.util.RandomAccessMode;
import com.github.junrar.Archive;
import com.github.junrar.Volume;
import com.github.junrar.io.IReadOnlyAccess;
import com.github.junrar.io.InputStreamReadOnlyAccessFile;
/**
* @author Rogiel
*/
public class VFSVolume implements Volume {
private final Archive archive;
private final FileObject file;
/**
* @param archive
* @param firstVolume
*/
public VFSVolume(Archive archive, FileObject file) {
this.archive = archive;
this.file = file;
}
@Override
public IReadOnlyAccess getReadOnlyAccess() throws IOException {
IReadOnlyAccess input = null;
try {
RandomAccessContent rac = file.getContent().getRandomAccessContent(
RandomAccessMode.READ);
input = new RandomAccessContentAccess(rac);
} catch (Exception e) {
input = new InputStreamReadOnlyAccessFile(file.getContent()
.getInputStream());
}
return input;
}
@Override
public long getLength() {
try {
return file.getContent().getSize();
} catch (FileSystemException e) {
return -1;
}
}
@Override
public Archive getArchive() {
return archive;
}
/**
* @return the file
*/
public FileObject getFile() {
return file;
}
}
================================================
FILE: unrar/src/main/java/com/github/junrar/vfs2/provider/rar/VFSVolumeManager.java
================================================
/*
* This file is part of seedbox .
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see .
*/
package com.github.junrar.vfs2.provider.rar;
import java.io.IOException;
import org.apache.commons.vfs2.FileObject;
import com.github.junrar.Archive;
import com.github.junrar.Volume;
import com.github.junrar.VolumeManager;
import com.github.junrar.util.VolumeHelper;
/**
* @author Rogiel
*/
public class VFSVolumeManager implements VolumeManager {
private final FileObject firstVolume;
/**
* @param firstVolume
*/
public VFSVolumeManager(FileObject firstVolume) {
this.firstVolume = firstVolume;
}
@Override
public Volume nextArchive(Archive archive, Volume last) throws IOException {
if (last == null)
return new VFSVolume(archive, firstVolume);
VFSVolume vfsVolume = (VFSVolume) last;
boolean oldNumbering = !archive.getMainHeader().isNewNumbering()
|| archive.isOldFormat();
String nextName = VolumeHelper.nextVolumeName(vfsVolume.getFile()
.getName().getBaseName(), oldNumbering);
FileObject nextVolumeFile = firstVolume.getParent().resolveFile(
nextName);
return new VFSVolume(archive, nextVolumeFile);
}
}