summaryrefslogtreecommitdiff
path: root/src/org/catacombae/rarx
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2012-10-19 11:32:57 +0400
committerAndrew Dolgov <[email protected]>2012-10-19 11:32:57 +0400
commit4ed357774aa94ad8be60ec9d257cc414462a0dc6 (patch)
treecd19a8114a952de41d196134567f21a997b406f4 /src/org/catacombae/rarx
parent354cef3a9c4e020aef9afeee12f846e4554ec7b7 (diff)
switch to junrar library
Diffstat (limited to 'src/org/catacombae/rarx')
-rw-r--r--src/org/catacombae/rarx/.cvsignore5
-rw-r--r--src/org/catacombae/rarx/CommentHeader.java54
-rw-r--r--src/org/catacombae/rarx/DecompressionCode.java1715
-rw-r--r--src/org/catacombae/rarx/FileAttributes.java29
-rw-r--r--src/org/catacombae/rarx/InvalidDataException.java29
-rw-r--r--src/org/catacombae/rarx/Leaf.java7
-rw-r--r--src/org/catacombae/rarx/ListArchiveContents.java438
-rw-r--r--src/org/catacombae/rarx/ListFilesInArchive.java173
-rw-r--r--src/org/catacombae/rarx/ListRecursive.java92
-rw-r--r--src/org/catacombae/rarx/MarkHeader.java48
-rw-r--r--src/org/catacombae/rarx/NewFileHeader.java428
-rw-r--r--src/org/catacombae/rarx/NewMainArchiveHeader.java94
-rw-r--r--src/org/catacombae/rarx/ProtectedHeader.java67
-rw-r--r--src/org/catacombae/rarx/RARFile.java248
-rw-r--r--src/org/catacombae/rarx/RARFile2.java29
-rw-r--r--src/org/catacombae/rarx/RARFileEntry.java76
-rw-r--r--src/org/catacombae/rarx/RARFileEntryStream.java550
-rw-r--r--src/org/catacombae/rarx/RARHeader.java121
-rw-r--r--src/org/catacombae/rarx/README.txt10
-rw-r--r--src/org/catacombae/rarx/TestRAFProperties.java32
-rw-r--r--src/org/catacombae/rarx/Tree.java55
-rw-r--r--src/org/catacombae/rarx/TreeNode.java17
-rw-r--r--src/org/catacombae/rarx/UNIXFileAttributes.java66
-rw-r--r--src/org/catacombae/rarx/UnknownHeader.java54
-rw-r--r--src/org/catacombae/rarx/Util.java305
-rw-r--r--src/org/catacombae/rarx/Win32FileAttributes.java68
26 files changed, 0 insertions, 4810 deletions
diff --git a/src/org/catacombae/rarx/.cvsignore b/src/org/catacombae/rarx/.cvsignore
deleted file mode 100644
index 0de89ca..0000000
--- a/src/org/catacombae/rarx/.cvsignore
+++ /dev/null
@@ -1,5 +0,0 @@
-*~
-*#
-*.class
-.DS_Store
-Thumbs.db
diff --git a/src/org/catacombae/rarx/CommentHeader.java b/src/org/catacombae/rarx/CommentHeader.java
deleted file mode 100644
index e3c080c..0000000
--- a/src/org/catacombae/rarx/CommentHeader.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.io.PrintStream;
-
-public class CommentHeader extends NewFileHeader {
- // This file header type is observed under UnpVer 0x1d (RAR 2.9)
- // This file header type is actually an archive comment!
- /* This type of header has a structure extactly like the NewFileHeader, but
- with a different head type (0x7a). The filename is probably always "CMT"
- (for "Comment"), and the data found when extracting it is the archive
- comment. */
-
- public CommentHeader(byte[] data, int offset) {
- super(data, offset);
- //super.super.validateData();
- }
-
- protected void validateData() {
- //print(System.out, "");
- //super.super.validateData(); //arvsproblem...
- if(getHeadType() != COMMENT_HEAD)
- throw new InvalidDataException("Incorrect head type! (headType=" + getHeadType() + ")");
- if(getHeadSize() < getStaticSize())
- throw new InvalidDataException("Invalid size! (size=" + getHeadSize() + ")");
- if(getHostOSAsString() == null)
- throw new InvalidDataException("Host OS value invalid.");
-
- }
-
- public void print(PrintStream ps, String prefix) {
- ps.println(prefix + "CommentHeader: ");
- printFields(ps, prefix);
- }
-}
diff --git a/src/org/catacombae/rarx/DecompressionCode.java b/src/org/catacombae/rarx/DecompressionCode.java
deleted file mode 100644
index 20f79f2..0000000
--- a/src/org/catacombae/rarx/DecompressionCode.java
+++ /dev/null
@@ -1,1715 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-//import org.catacombae.rarx.*;
-import java.math.BigInteger;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.util.zip.CRC32;
-
-public class DecompressionCode {
- private static final int MAXWINSIZE = 0x100000;
- private static final int MAXWINMASK = (MAXWINSIZE-1);
- private static final int UNP_MEMORY = MAXWINSIZE;
-
- public static final short NC = 298; /* alphabet = {0,1,2, .,NC - 1} */
- public static final short DC = 48;
- public static final short RC = 28;
- public static final short BC = 19;
- public static final short MC = 257;
-
- public static final int CODE_HUFFMAN = 0;
- public static final int CODE_LZ = 1;
- public static final int CODE_LZ2 = 2;
- public static final int CODE_REPEATLZ = 3;
- public static final int CODE_CACHELZ = 4;
- public static final int CODE_STARTFILE = 5;
- public static final int CODE_ENDFILE = 6;
- public static final int CODE_ENDMM = 7;
- public static final int CODE_STARTMM = 8;
- public static final int CODE_MMDELTA = 9;
-
- public static final int LHD_SPLIT_BEFORE = 1; //flag bit 0
- public static final int LHD_SPLIT_AFTER = 2; //flag bit 1
- public static final int LHD_PASSWORD = 4; //flag bit 2
- public static final int LHD_COMMENT = 8; //flag bit 3
- public static final int LHD_SOLID = 16; //flag bit 4
-
- public static final int LHD_WINDOWMASK = 0x00e0;
- public static final int LHD_WINDOW64 = 0;
- public static final int LHD_WINDOW128 = 32;
- public static final int LHD_WINDOW256 = 64;
- public static final int LHD_WINDOW512 = 96;
- public static final int LHD_WINDOW1024 = 128;
- public static final int LHD_DIRECTORY = 0x00e0;
-
- public static final int NROUNDS = 32;
-
- /* Static variables belonging to the function Unpack. */
- private static final short[] 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}; //unsigned char[14]
- private static final byte[] LBits = {0,0,0,0,0,0,0,0,1,1,1,1,2,2, //unsigned char[14]
- 2,2,3,3,3,3,4,4,4,4,5,5,5,5};
- private 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}; //int[48]
- private static final byte[] 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}; //unsigned char[48]
- private static final short[] SDDecode = {0,4,8,16,32,64,128,192}; //unsigned char[8]
- private static final byte[] SDBits = {2,2,3,4,5,6,6,6}; //unsigned char[8]
-
- public static final /*UBYTE*/ short[] InitSubstTable = {
- 215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221, 2, 42
- ,232, 1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137
- ,255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86, 6
- , 71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235
- ,107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36
- ,158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251
- , 97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11
- ,164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51
- ,207,120,189,210, 8,226, 41, 72,183,203,135,165,166, 60, 98, 7
- ,122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80
- ,131, 3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129
- ,224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10
- ,118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45, 4,148,108
- ,161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225
- , 0, 46,169,186, 68, 95,237, 65, 53,208,253,168, 9, 18,100, 52
- ,116,184,160, 96,109, 37, 30,106,140,104,150, 5,204,117,112, 84
- }; // UBYTE[256]
- public static final /*UDWORD*/ int[] CRCTab = new int[256]; // Initialized in static constructor
-
- static {
- // Perform initialization of static structures and variables.
- //CRCTab = new int[256];
- InitCRC(CRCTab);
- }
-
- private CRC32 crc = new CRC32();
-
- public final /*UBYTE*/ short[] SubstTable = new short[256];
-
- private /*unsigned*/ byte PN1, PN2, PN3;
-
- /* Note: temp_output_buffer is allocated when a file is about to be
- extracted. It is allocated to NewLhd.UnpSize, which can be quite
- large. The assumption that the unpacked file can be stored in
- memory is awkward and must immediately be replaced with an output
- stream. */
- private /* unsigned char* */ byte[] temp_output_buffer; /* extract files to this pointer*/
- private /* unsigned long* */ int temp_output_buffer_offset; /* size of temp. extract buffer */
- //private /*unsigned int*/ int UnpPtr,WrPtr;
- private final /*unsigned short*/ short[] OldKey = new short[4];
-
- private static class Decode {
- public int MaxNum; // unsigned int
- public final int[] DecodeLen = new int[16]; // unsigned int[16]
- public final int[] DecodePos = new int[16]; // unsigned int[16]
- public final int[] DecodeNum; // unsigned int[]
-
- public Decode() {
- this(2);
- }
-
- protected Decode(int decodeNumSize) { DecodeNum = new int[decodeNumSize]; }
- }
- private static class LitDecode extends Decode {
- public LitDecode() { super(NC); }
- }
- private static class DistDecode extends Decode {
- public DistDecode() { super(DC); }
- }
- private static class RepDecode extends Decode {
- public RepDecode() { super(RC); }
- }
- private static class MultDecode extends Decode {
- public MultDecode() { super(MC); }
- }
- private static class BitDecode extends Decode {
- public BitDecode() { super(BC); }
- }
-
- private final LitDecode LD = new LitDecode();
- private final DistDecode DD = new DistDecode();
- private final RepDecode RD = new RepDecode();
- private final MultDecode[] MD = { new MultDecode(), new MultDecode(),
- new MultDecode(), new MultDecode() }; //new MultDecode[4];
- private final BitDecode BD = new BitDecode();
-
- private final MultDecode[] MDPtr = { MD[0], MD[1], MD[2], MD[3] };
-
-
- /* *****************************
- * ** unpack stored RAR files **
- * *****************************/
-
-// BOOL UnstoreFile(void)
-// {
-// if ((long)(*temp_output_buffer_offset=UnpRead(temp_output_buffer,
-// NewLhd.UnpSize))==-1)
-// {
-// debug_log("Read error of stored file!");
-// return FALSE;
-// }
-// return TRUE;
-// }
-
-
-
-
- /* ****************************************
- * ** RAR decompression code starts here **
- * ****************************************/
-
- /* #define statements */
- public static class AudioVariables {
- public int K1,K2,K3,K4,K5; // Should be short...?
- public int D1,D2,D3,D4;
- public int LastDelta;
- public final int[] Dif = new int[11]; //unsigned
- public int ByteCount; //unsigned
- public int LastChar;
-
- public void zero() {
- K1 = 0;
- K2 = 0;
- K3 = 0;
- K4 = 0;
- K5 = 0;
- D1 = 0;
- D2 = 0;
- D3 = 0;
- D4 = 0;
- LastDelta = 0;
- Util.zero(Dif);
- ByteCount = 0;
- LastChar = 0;
- }
- }
-
- public AudioVariables[] AudV = { new AudioVariables(), new AudioVariables(),
- new AudioVariables(), new AudioVariables() };
-
- /*
-#define GetBits() \
- BitField = ( ( ( (UDWORD)InBuf[InAddr] << 16 ) | \
- ( (UWORD) InBuf[InAddr+1] << 8 ) | \
- ( InBuf[InAddr+2] ) ) \
- >> (8-InBit) ) & 0xffff;
- */
- private static int GetBits(byte[] inBuf, int inAddr, int inBit) {
- return ( ( ( (int) (inBuf[inAddr]&0xFF) << 16 ) |
- ( (short) (inBuf[inAddr+1]&0xFF) << 8 ) |
- ( (inBuf[inAddr+2]&0xFF) ) )
- >>> (8-unsign(inBit)) ) & 0xffff;
- }
-
- /*
-#define AddBits(Bits) \
- InAddr += ( InBit + (Bits) ) >> 3; \
- InBit = ( InBit + (Bits) ) & 7;
- */
-
- /**
- * Adds <code>Bits</code> to the address specifiers.
- * InAddr is the high 32 bits of the 35-bit address (?) while InBit is the low 3 bits (?).
- * Modifies: InAddr, InBit
- * @param Bits the bits to add (interpreted as unsigned int)
- */
- private void AddBits(int Bits) {
- InAddr += (int)(( unsign(InBit) + unsign(Bits) ) >>> 3); // (InBit + Bits) / 8
- InBit = (int)(( unsign(InBit) + unsign(Bits) ) & 7);
- }
-
- public static int unsign(byte i) {
- return i & 0xFF;
- }
- public static int unsign(short i) {
- return i & 0xFFFF;
- }
- public static long unsign(int i) {
- return i & 0xFFFFFFFFL;
- }
- public static BigInteger unsign(long i) {
- return new BigInteger(1, Util.toByteArrayBE(i));
- }
-
- private static class Struct_NewFileHeader {
- short HeadCRC;
- byte HeadType;
- short Flags;
- short HeadSize;
- int PackSize;
- int UnpSize;
- byte HostOS;
- int FileCRC;
- int FileTime;
- byte UnpVer;
- byte Method;
- short NameSize;
- int FileAttr;
- };
- private NewFileHeader NewLhd;// = new NewFileHeader();
-
- private RARFileEntryStream ArcPtr = null;
- private int Encryption;
- private long UnpPackedSize;
- private /*unsigned long*/ int CurUnpRead, CurUnpWrite;
-
- //private byte[] UnpBuf;
- private int BitField; //unsigned int
- //private int Number; //unsigned int
-
- public final byte[] InBuf = new byte[8192]; /* input read buffer */
-
- public final byte[] UnpOldTable = new byte[MC*4];
-
- public int InAddr,InBit,ReadTop; //unsigned int
-
- //public int LastDist,LastLength; //unsigned int
- //private int Length,Distance; //unsigned int
-
- //public final int[] OldDist = new int[4]; //unsigned int
- //public int OldDistPtr; //unsigned int
-
-
- public int UnpAudioBlock;
- public int UnpChannels;
- public int CurChannel;
- public int ChannelDelta;
- private boolean FileFound;
-
-
- /* *** 38.3% of all CPU time is spent within this function!!! */
- /**
- * Unpacks stuff.<p>
- *
- * <pre>
- * Global read set (constants):
- * DBits (final byte[48])
- * DDecode (final int[48])
- * LBits (final byte[14])
- * LDecode (final short[14])
- * LHD_SOLID (final int)
- * MAXWINMASK (final int)
- * MDPtr (final {@link MultDecode}[4])
- * SDBits (final byte[8])
- * SDDecode (final short[8])
- *
- * Global read set (variables):
- * FileFound (boolean)
- * NewLhd ({@link Struct_NewFileHeader})
- *
- * Global modify set:
- * BitField (int)
- * CurChannel (int)
- * DD (final {@link DistDecode})
- * InAddr (int)
- * InBit (int)
- * InBuf (final byte[8192])
- * LD (final {@link LitDecode})
- * temp_output_buffer (byte[])
- * temp_output_buffer_offset (int)
- * UnpAudioBlock (int)
- * UnpChannels (int)
- *
- * Local use set:
- * Bits (int)
- * (in) DestUnpSize (long)
- * Distance (int)
- * LastDist (int)
- * LastLength (int)
- * Length (int)
- * Number (int)
- * OldDist (final int[4])
- * OldDistPtr (int)
- * (in) UnpAddr (byte[])
- * UnpBuf (byte[])
- * UnpPtr (int)
- * WrPtr (int)
- *
- * Call set:
- * {@link #UnpInitData}
- * {@link #UnpReadBuf}
- * {@link #ReadTables}
- * {@link #debug_log}
- * {@link System#arraycopy}
- * {@link #DecodeNumber}
- * {@link #DecodeAudio}
- * {@link #GetBits}
- * {@link #AddBits}
- * {@link #ReadLastTables}
- * </pre>
- */
- public void Unpack(/*unsigned char*/ byte[] UnpAddr, /*long DestUnpSize, */RARFileEntryStream i_ArcPtr, OutputStream dataOut, NewFileHeader i_NewLhd) throws IOException {
- // catacombae
- ArcPtr = i_ArcPtr;
- NewLhd = i_NewLhd;
- long DestUnpSize = NewLhd.getUnpSize();
- UnpPackedSize = NewLhd.getPackSize();
- FileFound = true; //Otherwise no data will be written, just uncompressed and skipped (for the purpose of extracting solid archives).
- Encryption = 0;
- CurUnpRead = CurUnpWrite = 0;
- // /catacombae
-
- int Bits; // unsigned int
-
- byte[] UnpBuf=UnpAddr; /* UnpAddr is a pointer to the unpack buffer */
- int UnpPtr = 0; // Pointer to where in the buffer we are at present
- int WrPtr = 0; // Pointer to where in the buffer UnpBuf we were at the last write
- int Length = 0;
- int Distance = 0;
- int LastDist = 0;
- int LastLength = 0;
- int Number = 0;
- final int[] OldDist = new int[4];
- int OldDistPtr = 0;
-
- System.out.println("UnpInitData");
- UnpInitData(UnpBuf);
- System.out.println("UnpReadBuf");
- UnpReadBuf(true);
- if((NewLhd.getFlags() & LHD_SOLID) == 0) {
- System.out.println("ReadTables");
- ReadTables();
- }
-
- DestUnpSize--;
-
- int l256 = 0, g269 = 0, e269 = 0, e256 = 0, l261 = 0, l270 = 0; // debug / understanding
- while(DestUnpSize>=0) {
- System.out.println("Looping (DestUnpSize=" + DestUnpSize + ")");
- UnpPtr &= MAXWINMASK;
-
- if(unsign(InAddr) > InBuf.length-30)
- UnpReadBuf(false);
- if(((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr) {
- System.out.println("YO");
- if(FileFound) {
- // Flush extracted data to file
- if(!writeData(UnpBuf, UnpPtr, WrPtr, dataOut))
- DestUnpSize = -1;
- }
- WrPtr=UnpPtr;
- }
- else {
- //System.out.println("((" + WrPtr + "-" + UnpPtr + ") & MAXWINMASK) >= 270");
- //System.out.println(((WrPtr-UnpPtr) & MAXWINMASK) + "<270");
- }
-
- if(UnpAudioBlock != 0) {
- Number = DecodeNumber(MDPtr[CurChannel]);
- if (Number==256) {
- ReadTables();
- }
- else {
- UnpBuf[UnpPtr++]=DecodeAudio(Number);
- if (++CurChannel==UnpChannels)
- CurChannel=0;
- DestUnpSize--;
- }
- //continue;
- }
- else {
- Number = DecodeNumber(LD);
- if(Number<256) { // stored
- System.out.println(Number);
- ++l256;
- UnpBuf[UnpPtr++]=(byte)Number;
- DestUnpSize--;
- //continue;
- }
- else if(Number>269) {
- ++g269;
- Length = LDecode[Number-=270]+3;
- if ((Bits=LBits[Number])>0) {
- BitField = GetBits(InBuf, InAddr, InBit);
- Length+=BitField>>>(16-Bits);
- AddBits(Bits);
- }
-
- Number = DecodeNumber(DD);
- Distance = DDecode[Number]+1;
- if ((Bits=DBits[Number])>0) {
- BitField = GetBits(InBuf, InAddr, InBit);
- Distance += BitField >>> (16-Bits);
- AddBits(Bits);
- }
-
- if (Distance>=0x40000)
- Length++;
-
- if (Distance>=0x2000)
- Length++;
-
- LastDist=OldDist[OldDistPtr++ & 3]=Distance;
- DestUnpSize-=(LastLength=Length);
- while (Length-- != 0) {
- UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
- UnpPtr=(UnpPtr+1) & MAXWINMASK;
- }
-
- //continue;
- }
- else if(Number==269) {
- ++e269;
- ReadTables();
- //continue;
- }
- else if(Number==256) {
- ++e256;
- Length = LastLength;
- Distance = LastDist;
- LastDist = OldDist[OldDistPtr++ & 3] = Distance;
- DestUnpSize -= (LastLength=Length);
- while(Length-- != 0) {
- UnpBuf[UnpPtr] = UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
- UnpPtr = (UnpPtr+1) & MAXWINMASK;
- }
- //continue;
- }
- else if(Number<261) {
- ++l261;
- Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
- Number = DecodeNumber(RD);
- Length=LDecode[Number]+2;
- if ((Bits=LBits[Number])>0) {
- BitField = GetBits(InBuf, InAddr, InBit);
- Length+=BitField>>>(16-Bits);
- AddBits(Bits);
- }
- if (Distance>=0x40000)
- Length++;
- if (Distance>=0x2000)
- Length++;
- if (Distance>=0x101)
- Length++;
- LastDist=OldDist[OldDistPtr++ & 3]=Distance;
- DestUnpSize-=(LastLength=Length);
- while (Length-- != 0) {
- UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
- UnpPtr=(UnpPtr+1) & MAXWINMASK;
- }
- //continue;
- }
- else if(Number<270) {
- ++l270;
- Distance=SDDecode[Number-=261]+1;
- if ((Bits=SDBits[Number])>0) {
- BitField = GetBits(InBuf, InAddr, InBit);
- Distance+=BitField>>>(16-Bits);
- AddBits(Bits);
- }
- Length=2;
- LastDist=OldDist[OldDistPtr++ & 3]=Distance;
- DestUnpSize-=(LastLength=Length);
- while (Length-- != 0) {
- UnpBuf[UnpPtr]=UnpBuf[(UnpPtr-Distance) & MAXWINMASK];
- UnpPtr=(UnpPtr+1) & MAXWINMASK;
- }
- //continue;
- }
- else
- debug_log("This message will NEVER be printed. If it is printed anyway, kick the programmer.");
- }
- }
- System.out.println("x < 256: " + l256);
- System.out.println("x > 269: " + g269);
- System.out.println("x = 269: " + e269);
- System.out.println("x = 256: " + e256);
- System.out.println("x < 261: " + l261);
- System.out.println("x < 270: " + l270);
- System.out.println("Total: " + (l256+g269+e269+e256+l261+l270));
- System.out.println("LD.DecodeLen: 0x" + Util.toHexStringBE(LD.DecodeLen));
- System.out.println("LD.DecodeNum: 0x" + Util.toHexStringBE(LD.DecodeNum));
- System.out.println("LD.DecodePos: 0x" + Util.toHexStringBE(LD.DecodePos));
- System.out.println("LD.MaxNum: 0x" + Util.toHexStringBE(LD.MaxNum));
- ReadLastTables();
-
- if (FileFound) { /* flush buffer */
- // Flush extracted data to file
- if(!writeData(UnpBuf, UnpPtr, WrPtr, dataOut))
- DestUnpSize = -1;
- }
-
- WrPtr=UnpPtr;
- }
-
- /**
- * Writes the data in <code>UnpBuf</code> to <code>dataOut</code> according to some rules.<p>
- * <pre>
- * Global read set:
- * {@link #NewLhd} ({@link NewFileHeader})
- *
- * Global modify set:
- * *temp_output_buffer (byte[])
- * temp_output_buffer_offset (int)
- *
- * Local use set:
- * (in) UnpBuf (byte[])
- * </pre>
- */
- private boolean writeData(byte[] UnpBuf, int UnpPtr, int WrPtr, OutputStream dataOut) throws IOException {
- if (UnpPtr<WrPtr) {
- debug_log("UnpPtr<WrPtr (" + UnpPtr + "<" + WrPtr + ")");
- if((temp_output_buffer_offset + UnpPtr) > NewLhd.getUnpSize()) {
- debug_log("Fatal! Buffer overrun during decompression!");
- return false; //DestUnpSize=-1;
- } else if(true) {
- int firstOutLengthOld = (0-WrPtr) & MAXWINMASK; // Don't understand...
- int firstOutLength = (UnpBuf.length-1) - WrPtr; //This should be equivalent to the above
- if(firstOutLengthOld != firstOutLength)
- debug_log("Assumption broken for firstOutLength :(");
-
- dataOut.write(UnpBuf, WrPtr, firstOutLength);
- dataOut.write(UnpBuf, 0, UnpPtr);
- temp_output_buffer_offset += firstOutLength+UnpPtr;
- } else {
- int firstOutLength = (0-WrPtr) & MAXWINMASK; // Don't understand...
- /* copy extracted data to output buffer */
- System.arraycopy(UnpBuf, WrPtr, temp_output_buffer, temp_output_buffer_offset, firstOutLength);
- /* update offset within buffer */
- temp_output_buffer_offset += firstOutLength;
- /* copy extracted data to output buffer */
- System.arraycopy(UnpBuf, 0, temp_output_buffer, temp_output_buffer_offset, UnpPtr);
- /* update offset within buffer */
- temp_output_buffer_offset += UnpPtr;
- }
- } else {
- debug_log("UnpPtr>WrPtr (" + UnpPtr + ">" + WrPtr + ")");
-
- if((temp_output_buffer_offset + (UnpPtr-WrPtr)) > NewLhd.getUnpSize()) {
- debug_log("Fatal! Buffer overrun during decompression!");
- //DestUnpSize=-1;
- return false;
- } else if(true) {
- dataOut.write(UnpBuf, WrPtr, UnpPtr-WrPtr);
- temp_output_buffer_offset += UnpPtr-WrPtr;
- } else {
- /* copy extracted data to output buffer */
- System.arraycopy(UnpBuf, WrPtr, temp_output_buffer, temp_output_buffer_offset, UnpPtr-WrPtr);
- temp_output_buffer_offset+=UnpPtr-WrPtr; /* update offset within buffer */
- }
- }
- return true;
- }
- /**
- * Reads into the buffer <code>InBuf</code> from the archive stream. If the flag FirstBuf
- * is set, the method preserves the last 32 bytes of InBuf and copies them to the front
- * of the buffer, filling the buffer with only <code>InBuf.length-32</code> bytes.<p>
- * <pre>
- * Global modify set:
- * ReadTop (int)
- * InAddr (int)
- * Through UnpRead:
- * UnpPackedSize (int)
- * CurUnpRead (int)
- *
- * Global read set:
- * InBuf (byte[]) (contents modified in UnpRead)
- *
- * Local use set:
- * (in) FirstBuf (boolean)
- * RetCode (int)
- *
- * Call set:
- * {@link UnpRead}
- * </pre>
- * @param FirstBuf flag indicating whether or not we will treat this read as the first read
- * to the buffer, thus destroying any previous content
- */
- private void UnpReadBuf(boolean FirstBuf) {
- int RetCode;
- if(FirstBuf) {
- ReadTop = UnpRead(InBuf, 0, InBuf.length);
- InAddr = 0;
- }
- else {
- System.arraycopy(InBuf, InBuf.length-32, InBuf, 0, 32);
- InAddr &= 0x1f; // discard all but the five least significant bytes... is this modulo 32? think so.
- RetCode = UnpRead(InBuf, 32, InBuf.length-32);
- if(RetCode > 0)
- ReadTop=RetCode+32;
- else
- ReadTop=InAddr;
- }
- }
-
- /**
- * Reads <code>Count</code> bytes from the stream <code>ArcPtr</code> into
- * the buffer <code>Addr</code> at position <code>offset</code>. If the
- * data is encrypted, it is automatically decrypted. (The variable
- * <code>Encryption</code> tells the function whether is shall consider
- * the data to be encrypted.)<p>
- * <pre>
- * Global read set:
- * ArcPtr ({@link java.io.InputStream})
- * Encryption (int)
- *
- * Global modify set:
- * UnpPackedSize (int)
- * CurUnpRead (int)
- *
- * Local use set:
- * (in) Addr (byte[])
- * (in) offset (int)
- * (in) Count (int)
- * RetCode (int)
- * I (int)
- * ReadSize (int)
- * TotalRead (int)
- * ReadAddr (byte[])
- * readAddrPointer (int)
- *
- * Call set:
- * tread(File, byte[], int, int)
- * debug_log(String)
- * DecryptBlock(byte[], int, int)
- * </pre>
- * @return the number of bytes read, or -1 if an error occurred.
- */
- private /*unsigned int*/ int UnpRead(/*unsigned char **/ byte[] Addr, int offset, /*unsigned int*/ int Count) {
- int RetCode=0;
- /*unsigned int*/ int I,ReadSize,TotalRead=0;
- /*unsigned char **/ byte[] ReadAddr;
- int readAddrPointer = offset; // catacombae
- ReadAddr=Addr;
- while(Count > 0) {
- ReadSize=(/*unsigned int*/ int)((Count>(/*unsigned long*/ int)UnpPackedSize) ?
- UnpPackedSize : Count);
- if (ArcPtr==null)
- return(0);
- RetCode=tread(ArcPtr,ReadAddr,readAddrPointer,ReadSize);
- debug_log("Read " + RetCode + " from file.");
-
- CurUnpRead+=RetCode;
- readAddrPointer+=RetCode;
- TotalRead+=RetCode;
- Count-=RetCode;
- UnpPackedSize-=RetCode;
- break; // Why the while-loop? if would work just as well.
- }
- if (RetCode!= -1) {
- RetCode=TotalRead;
- if (Encryption != 0) {
- if (Encryption<20) {
- debug_log("Old Crypt() not supported!");
- }
- else {
- for (I=0;I<(/*unsigned int*/ short)RetCode;I+=16)
- DecryptBlock(/*&Addr[I]*/Addr, I);
- }
- }
- }
- return(RetCode);
- }
-
-
- /**
- * Reads and initializes the decompression tables.<p>
- * <pre>
- * Global read set (constants):
- * BC (final short)
- * DC (final short)
- * MC (final short)
- * NC (final short)
- * RC (final short)
- *
- * Global read set (variables):
- *
- * Global modify set:
- * BD (BitDecode)
- * BitField (int)
- * CurChannel (int)
- * DD (DistDecode)
- * InAddr (int)
- * InBit (int) (through AddBits)
- * InBuf (final byte[8192])
- * MDPtr (final MultDecode[4])
- * RD (RepDecode)
- * UnpAudioBlock (int)
- * UnpChannels (int)
- * UnpOldTable (final byte[MC*4])
- *
- *
- * Local use set:
- * BitLength (final byte[BC])
- * Table (final byte[MC*4])
- * TableSize (int)
- * N (int)
- * I (int)
- *
- * Call set:
- * UnpReadBuf
- * GetBits
- * Util.zero
- * AddBits
- * MakeDecodeTables
- * DecodeNumber
- * System.arraycopy
- * </pre>
- */
- private void ReadTables() {
- System.out.println("ReadTables():");
- final /*UBYTE*/ byte[] BitLength = new byte[BC];
- final /*unsigned char*/ byte[] Table = new byte[MC*4];
- /*int*/ int TableSize,N,I;
-
- if(InAddr>InBuf.length-25) {
- System.out.println("InAddr == " + InAddr);
- UnpReadBuf(false);
- }
- BitField = GetBits(InBuf, InAddr, InBit);
- UnpAudioBlock = (BitField & 0x8000);
-
- if((BitField & 0x4000) == 0)
- Util.zero(UnpOldTable);
- AddBits(2);
-
-
- if(UnpAudioBlock != 0) {
- UnpChannels=((BitField >>> 12) & 3)+1;
- debug_log("WARNING: UnpChannels = " + UnpChannels);
- if (CurChannel>=UnpChannels)
- CurChannel=0;
- AddBits(2);
- TableSize=(short)(MC*UnpChannels);
- }
- else
- TableSize=NC+DC+RC;
-
-
- for (I=0;I<BC;I++) {
- BitField = GetBits(InBuf, InAddr, InBit);
- BitLength[I]=(/*UBYTE*/byte)(BitField >>> 12);
- AddBits(4);
- }
- MakeDecodeTables(BitLength, BD, 0, BC);
-
- I=0;
- while(I<TableSize) {
- if(InAddr>InBuf.length-5)
- UnpReadBuf(false);
- int number = DecodeNumber(BD);
- if(number<16)
- Table[I++]=(byte)((number+UnpOldTable[I]) & 0xf);
- else
- if(number==16) {
- BitField = GetBits(InBuf, InAddr, InBit);
- N=((BitField >>> 14)+3);
- AddBits(2);
- while(N-- > 0 && I<TableSize) {
- Table[I]=Table[I-1];
- I++;
- }
- }
- else {
- if(number==17) {
- BitField = GetBits(InBuf, InAddr, InBit);
- N=((BitField >>> 13)+3);
- AddBits(3);
- }
- else {
- BitField = GetBits(InBuf, InAddr, InBit);
- N=((BitField >>> 9)+11);
- AddBits(7);
- }
- while(N-- > 0 && I<TableSize)
- Table[I++]=0;
- }
- }
- if(UnpAudioBlock != 0)
- for(I=0; I<UnpChannels; I++)
- MakeDecodeTables(Table, MDPtr[I], (I*MC), MC);
- else {
- MakeDecodeTables(Table, LD, 0, NC);
- MakeDecodeTables(Table, DD, NC, DC);
- MakeDecodeTables(Table, RD, (NC+DC), RC);
- }
-
- System.arraycopy(Table, 0, UnpOldTable, 0, UnpOldTable.length);
- }
-
-
- private void ReadLastTables() {
- if (ReadTop>=InAddr+5) {
- if (UnpAudioBlock != 0) {
- int number = DecodeNumber(MDPtr[CurChannel]);
- if (number==256)
- ReadTables();
- }
- else {
- int number = DecodeNumber(LD);
- if (number==269)
- ReadTables();
- }
- }
- }
-
- /**
- * Modifies the <code>Decode</code> object <code>Dec</code> supplied as parameter
- * according to the data in <code>LenTab</code>. Initializes <code>Dec</code> for
- * further use in decompression.<p>
- * <pre>
- * Global modify set:
- * <empty>
- *
- * Global read set:
- * <empty>
- *
- * Local use set:
- * (in) LenTab (byte[])
- * (i/o) Dec ({@link Decode})
- * (in) offset (int)
- * (in) Size (int)
- * LenCount (final int[16])
- * TmpPos (final int[16])
- * I (int)
- * M (int)
- * N (int)
- * </pre>
- */
- private void MakeDecodeTables(/*unsigned char **/ byte[] LenTab,
- Decode Dec,
- int offset,
- int Size) {
- final /*int*/int[] LenCount = new int[16];
- final /*int*/int[] TmpPos = new int[16];
- /*int*/int I;
- /*long*/int M, N;
- //memset(LenCount,0,sizeof(LenCount)); // Java does this automatically
- for(I=offset; I<offset+Size; I++)
- LenCount[LenTab[I] & 0xF]++;
-
- LenCount[0]=0;
- for(TmpPos[0]=Dec.DecodePos[0]=Dec.DecodeLen[0]=0,N=0,I=1; I<16; I++) {
- N = 2*(N+LenCount[I]);
- M = N << (15-I);
- if(M>0xFFFF)
- M=0xFFFF;
- Dec.DecodeLen[I]=(/*unsigned int*/int)M;
- TmpPos[I]=Dec.DecodePos[I]=((Dec.DecodePos[I-1] & 0xFFFF)+LenCount[I-1]);
- }
-
- for(I=offset; I<offset+Size; I++)
- if(LenTab[I]!=0)
- Dec.DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
- Dec.MaxNum=Size;
- }
-
-
- /* *** 52.6% of all CPU time is spent within this function!!! */
- /**
- * Decodes a number from the supplied <code>Decode</code> object.<p>
- * <pre>
- * Global modify set:
- * BitField (int)
- * In AddBits:
- * InAddr (int)
- * InBit (int)
- *
- * Local use set:
- * (in) Deco ({@link Decode})
- * I (int)
- * N (int)
- *
- * Call set:
- * GetBits
- * AddBits
- * </pre>
- *
- * @return the decoded number...?
- */
- private int DecodeNumber(Decode Deco) {
- /*unsigned int*/ int I;
- /*register unsigned int*/ int N;
- System.out.println("GetBits(" + InBuf + ", " + InAddr + ", " + InBit + ");");
- BitField = GetBits(InBuf, InAddr, InBit);
-
- N=(BitField & 0xFFFE);
- System.out.println("(1) N == " + N + " (BitField == " + BitField + ")");
- if(N<Deco.DecodeLen[8]) {
- if(N<Deco.DecodeLen[4]) {
- if(N<Deco.DecodeLen[2]) {
- if(N<Deco.DecodeLen[1])
- I=1;
- else
- I=2;
- } else {
- if(N<Deco.DecodeLen[3])
- I=3;
- else
- I=4;
- }
- } else {
- if(N<Deco.DecodeLen[6]) {
- if(N<Deco.DecodeLen[5])
- I=5;
- else
- I=6;
- } else {
- if(N<Deco.DecodeLen[7])
- I=7;
- else
- I=8;
- }
- }
- } else {
- if(N<Deco.DecodeLen[12]) {
- if(N<Deco.DecodeLen[10]) {
- if(N<Deco.DecodeLen[9])
- I=9;
- else
- I=10;
- } else {
- if(N<Deco.DecodeLen[11])
- I=11;
- else
- I=12;
- }
- } else {
- if(N<Deco.DecodeLen[14]) {
- if(N<Deco.DecodeLen[13])
- I=13;
- else
- I=14;
-
- } else {
- I=15;
- }
- }
-
- }
-
- AddBits(I);
- N = Deco.DecodePos[I] + ((N-Deco.DecodeLen[I-1]) >>> (16-I));
- System.out.println("(2) N == " + N);
- if(N >= Deco.MaxNum)
- N=0;
- System.out.println("(3) N == " + N);
-
- System.out.println("Deco.DecodeNum[" + N + "] == " + Deco.DecodeNum[N]);
- return Deco.DecodeNum[N];
- }
-
- /**
- * Intializes data for the unpack process by setting the variables <code>InAddr</code> and <code>InBit</code> to 0.<br>
- * If the archive is a solid archive the method also does the following:<br>
- * <ul>
- * <li>Set <code>ChannelDelta</code> and <code>CurChannel</code> to 0.</li>
- * <li>Zero all <code>AudioVariables</code> objects in <code>AudV</code> through {@link AudioVariables#zero}.</li>
- * <li>Zero the arrays <code>unpBuf</code> and <code>UnpOldTable</code>.</li>
- * </ul><p>
- * <pre>
- * Global read set:
- * NewLhd ({@link Struct_NewFileHeader})
- * LHD_SOLID (final int)
- * MAXWINSIZE (final int)
- *
- * Global modify set:
- * InAddr (int)
- * InBit (int)
- * ChannelDelta (int)
- * CurChannel (int)
- * AudV ({@link AudioVariables})
- *
- * Local use set:
- * (in) unpBuf (byte[])
- * </pre>
- */
- private void UnpInitData(byte[] unpBuf) {
- InAddr=InBit=0;
- if(!((NewLhd.getFlags() & LHD_SOLID) != 0)) {
- System.out.println("1");
- ChannelDelta=CurChannel=0;
-
- //memset(AudV,0,sizeof(AudV));
- System.out.println("2");
- for(AudioVariables av : AudV)
- av.zero();
- //memset(OldDist,0,sizeof(OldDist));
- //Util.zero(OldDist);
- //OldDistPtr=0;
- //LastDist=LastLength=0;
- //memset(UnpBuf,0,MAXWINSIZE);
- System.out.println("3");
- Util.zero(unpBuf, 0, MAXWINSIZE);
- //memset(UnpOldTable,0,sizeof(UnpOldTable));
- System.out.println("4");
- Util.zero(UnpOldTable);
- //UnpPtr=WrPtr=0;
- }
- }
-
- /**
- * Does some kind of audio decoding that I'm not familiar with conceptually.<p>
- * <pre>
- * Global read set:
- * CurChannel (int)
- *
- * Global modify set:
- * AudV ({@link AudioVariables}[])
- * ChannelDelta (int)
- *
- * Local use set:
- * (in) Delta (int)
- * V ({@link AudioVariables})
- * Ch (int)
- * NumMinDif (int)
- * MinDif (int)
- * PCh (int)
- * I (int)
- * </pre>
- */
- private /*UBYTE*/ byte DecodeAudio(int Delta) {
- AudioVariables V;
- /*unsigned */int Ch;
- /*unsigned */int NumMinDif,MinDif;
- int PCh,I;
-
- V=AudV[CurChannel];
- V.ByteCount++;
- V.D4=V.D3;
- V.D3=V.D2;
- V.D2=V.LastDelta-V.D1;
- V.D1=V.LastDelta;
- PCh=8*V.LastChar+V.K1*V.D1+V.K2*V.D2+
- V.K3*V.D3+V.K4*V.D4+V.K5*ChannelDelta;
- PCh=(PCh>>3) & 0xFF;
-
- Ch=PCh-Delta;
-
- I=((/*signed char*/byte)Delta)<<3;
-
- V.Dif[0]+=Math.abs(I);
- V.Dif[1]+=Math.abs(I-V.D1);
- V.Dif[2]+=Math.abs(I+V.D1);
- V.Dif[3]+=Math.abs(I-V.D2);
- V.Dif[4]+=Math.abs(I+V.D2);
- V.Dif[5]+=Math.abs(I-V.D3);
- V.Dif[6]+=Math.abs(I+V.D3);
- V.Dif[7]+=Math.abs(I-V.D4);
- V.Dif[8]+=Math.abs(I+V.D4);
- V.Dif[9]+=Math.abs(I-ChannelDelta);
- V.Dif[10]+=Math.abs(I+ChannelDelta);
-
- ChannelDelta=V.LastDelta=(/*signed char*/byte)(Ch-V.LastChar);
- V.LastChar=Ch;
-
- if((V.ByteCount & 0x1F)==0) {
- MinDif=V.Dif[0];
- NumMinDif=0;
- V.Dif[0]=0;
- for (I=1;(/*unsigned */int)I<V.Dif.length;I++) {
- if(V.Dif[I]<MinDif) {
- MinDif=V.Dif[I];
- NumMinDif=I;
- }
- V.Dif[I]=0;
- }
- switch(NumMinDif) {
- case 1:
- if(V.K1>=-16)
- V.K1--;
- break;
- case 2:
- if(V.K1<16)
- V.K1++;
- break;
- case 3:
- if(V.K2>=-16)
- V.K2--;
- break;
- case 4:
- if(V.K2<16)
- V.K2++;
- break;
- case 5:
- if(V.K3>=-16)
- V.K3--;
- break;
- case 6:
- if(V.K3<16)
- V.K3++;
- break;
- case 7:
- if(V.K4>=-16)
- V.K4--;
- break;
- case 8:
- if(V.K4<16)
- V.K4++;
- break;
- case 9:
- if(V.K5>=-16)
- V.K5--;
- break;
- case 10:
- if(V.K5<16)
- V.K5++;
- break;
- }
- }
- return((/*UBYTE*/byte)Ch);
- }
-
-
-
-
-
-
-
- /* ***************************************************
- * ** CRCCrypt Code - decryption engine starts here **
- * ***************************************************/
-
-
-
-/* #define rol(x,n) (((x)<<(n)) | ((x)>>(8*sizeof(x)-(n)))) */
- /** Rotate left. Pure functional behavior, no side effects. */
- private static byte rol(byte value, int shift) {
- return (byte) (((value)<<(shift)) | ((value)>>>(8*1-(shift))));
- }
- /** @see #rol(byte,int) */
- private static short rol(short value, int shift) {
- return (short)(((value)<<(shift)) | ((value)>>>(8*2-(shift))));
- }
- /** @see #rol(byte,int) */
- private static int rol(int value, int shift) {
- return (((value)<<(shift)) | ((value)>>>(8*4-(shift))));
- }
- /** @see #rol(byte,int) */
- private static long rol(long value, int shift) {
- return (((value)<<(shift)) | ((value)>>>(8*8-(shift))));
- }
-
-/* #define ror(x,n) (((x)>>(n)) | ((x)<<(8*sizeof(x)-(n)))) */
- /** Rotate right. Pure functional behavior, no side effects. */
- private static byte ror(byte value, int shift) {
- return (byte) (((value)>>>(shift)) | ((value)<<(8*1-(shift))));
- }
- /** @see #ror(byte,int) */
- private static short ror(short value, int shift) {
- return (short)(((value)>>>(shift)) | ((value)<<(8*2-(shift))));
- }
- /** @see #ror(byte,int) */
- private static int ror(int value, int shift) {
- return (((value)>>>(shift)) | ((value)<<(8*4-(shift))));
- }
- /** @see #ror(byte,int) */
- private static long ror(long value, int shift) {
- return (((value)>>>(shift)) | ((value)<<(8*8-(shift))));
- }
-
-/*
-#define substLong(t) ( (UDWORD)SubstTable[(int)t&255] | \
- ((UDWORD)SubstTable[(int)(t>> 8)&255]<< 8) | \
- ((UDWORD)SubstTable[(int)(t>>16)&255]<<16) | \
- ((UDWORD)SubstTable[(int)(t>>24)&255]<<24) )
-*/
- private int substLong(int t) {
- return ( ((/*UDWORD*/int)SubstTable[(int)(t>> 0)&255]<< 0) |
- ((/*UDWORD*/int)SubstTable[(int)(t>> 8)&255]<< 8) |
- ((/*UDWORD*/int)SubstTable[(int)(t>>16)&255]<<16) |
- ((/*UDWORD*/int)SubstTable[(int)(t>>24)&255]<<24) );
- }
-
- // public static final /*UDWORD*/ int[] CRCTab = new int[256]; // Initialized in static constructor
-
-
- public /*UDWORD*/ int[] Key = new int[4];
-
-
- public void EncryptBlock(/*UBYTE*/byte[] Buf) {
- //int I;
-
- int /*UDWORD*/ A,B,C,D,T,TA,TB;
-// #ifdef NON_INTEL_BYTE_ORDER
- if(true) {
- A = ((0xFF & Buf[0] ) | ((0xFF & Buf[1] )<<8) | ((0xFF & Buf[2] )<<16) | ((0xFF & Buf[3] )<<24))^Key[0];
- B = ((0xFF & Buf[4] ) | ((0xFF & Buf[5] )<<8) | ((0xFF & Buf[6] )<<16) | ((0xFF & Buf[7] )<<24))^Key[1];
- C = ((0xFF & Buf[8] ) | ((0xFF & Buf[9] )<<8) | ((0xFF & Buf[10])<<16) | ((0xFF & Buf[11])<<24))^Key[2];
- D = ((0xFF & Buf[12]) | ((0xFF & Buf[13])<<8) | ((0xFF & Buf[14])<<16) | ((0xFF & Buf[15])<<24))^Key[3];
- }
- else { // The above code should yield the same result as these lines. Test this assumption.
- A = Util.readIntLE(Buf, 0 )^Key[0];
- B = Util.readIntLE(Buf, 4 )^Key[1];
- C = Util.readIntLE(Buf, 8 )^Key[2];
- D = Util.readIntLE(Buf, 12)^Key[3];
- }
-// #else
-// UDWORD *BufPtr;
-// BufPtr=(UDWORD *)Buf;
-// A=BufPtr[0]^Key[0];
-// B=BufPtr[1]^Key[1];
-// C=BufPtr[2]^Key[2];
-// D=BufPtr[3]^Key[3];
-// #endif
- for(int I=0;I<NROUNDS;I++) {
- T=((C+rol(D,11))^Key[I&3]);
- TA=A^substLong(T);
- T=((D^rol(C,17))+Key[I&3]);
- TB=B^substLong(T);
- A=C;
- B=D;
- C=TA;
- D=TB;
- }
-// #ifdef NON_INTEL_BYTE_ORDER
- if(true) {
- C ^= Key[0];
- Buf[0]=(byte)(0xFF & C);
- Buf[1]=(byte)(0xFF & (C>>>8));
- Buf[2]=(byte)(0xFF & (C>>>16));
- Buf[3]=(byte)(0xFF & (C>>>24));
- D ^= Key[1];
- Buf[4]=(byte)(0xFF & D);
- Buf[5]=(byte)(0xFF & (D>>>8));
- Buf[6]=(byte)(0xFF & (D>>>16));
- Buf[7]=(byte)(0xFF & (D>>>24));
- A ^= Key[2];
- Buf[8]=(byte)(0xFF & A);
- Buf[9]=(byte)(0xFF & (A>>>8));
- Buf[10]=(byte)(0xFF & (A>>>16));
- Buf[11]=(byte)(0xFF & (A>>>24));
- B ^= Key[3];
- Buf[12]=(byte)(0xFF & B);
- Buf[13]=(byte)(0xFF & (B>>>8));
- Buf[14]=(byte)(0xFF & (B>>>16));
- Buf[15]=(byte)(0xFF & (B>>>24));
- }
- else {
- System.arraycopy(Util.toByteArrayLE(C^Key[0]), 0, Buf, 0, 4);
- System.arraycopy(Util.toByteArrayLE(D^Key[1]), 4, Buf, 0, 4);
- System.arraycopy(Util.toByteArrayLE(A^Key[2]), 8, Buf, 0, 4);
- System.arraycopy(Util.toByteArrayLE(B^Key[3]), 12, Buf, 0, 4);
- }
-// #else
-// BufPtr[0]=C^Key[0];
-// BufPtr[1]=D^Key[1];
-// BufPtr[2]=A^Key[2];
-// BufPtr[3]=B^Key[3];
-// #endif
- UpdKeys(Buf);
-}
-
-
- /**
- * Decrypts a 16 byte block in the buffer <code>Buf</code> at position <code>offset</code>.
- * The decrypted data is stored at the same place in <code>Buf</code>, thus overwriting the
- * encrypted contents.<p>
- * <pre>
- * Global read set:
- *
- * Global modify set:
- * In UpdKeys:
- * Key (final int[4])
- *
- * Local use set:
- * (in) Buf (byte[])
- * (in) offset (int)
- * InBuf (byte[])
- * A (int)
- * B (int)
- * C (int)
- * D (int)
- * T (int)
- * TA (int)
- * TB (int)
- * </pre>
- */
- public void DecryptBlock(/*UBYTE*/byte[] Buf, int offset) {
- //int I;
- final int n = offset;
- byte[] /*UBYTE*/ InBuf = new byte[16];
- int /*UDWORD*/ A,B,C,D,T,TA,TB;
- System.arraycopy(Buf, n, InBuf, 0, InBuf.length); // memcpy(InBuf,Buf,sizeof(InBuf));
-
- // Swap all bytes since data is stored in little endian format.
-// if(true) {
- A = ((0xFF & Buf[n+0] ) | ((0xFF & Buf[n+1] )<<8) | ((0xFF & Buf[n+2] )<<16) | ((0xFF & Buf[n+3] )<<24))^Key[0];
- B = ((0xFF & Buf[n+4] ) | ((0xFF & Buf[n+5] )<<8) | ((0xFF & Buf[n+6] )<<16) | ((0xFF & Buf[n+7] )<<24))^Key[1];
- C = ((0xFF & Buf[n+8] ) | ((0xFF & Buf[n+9] )<<8) | ((0xFF & Buf[n+10])<<16) | ((0xFF & Buf[n+11])<<24))^Key[2];
- D = ((0xFF & Buf[n+12]) | ((0xFF & Buf[n+13])<<8) | ((0xFF & Buf[n+14])<<16) | ((0xFF & Buf[n+15])<<24))^Key[3];
-// }
-// else { // The above code should yield the same result as these lines. Test this assumption.
- int A2 = Util.readIntLE(Buf, n+0 )^Key[0];
- int B2 = Util.readIntLE(Buf, n+4 )^Key[1];
- int C2 = Util.readIntLE(Buf, n+8 )^Key[2];
- int D2 = Util.readIntLE(Buf, n+12)^Key[3];
-// }
-
- if(A != A2 || B != B2 || C != C2 || D != D2) {
- System.out.println("Assumption broken!");
- System.out.println(" A: 0x" + Util.toHexStringBE(A) + " A2: 0x" + Util.toHexStringBE(A2));
- System.out.println(" B: 0x" + Util.toHexStringBE(B) + " B2: 0x" + Util.toHexStringBE(B2));
- System.out.println(" C: 0x" + Util.toHexStringBE(C) + " C2: 0x" + Util.toHexStringBE(C2));
- System.out.println(" D: 0x" + Util.toHexStringBE(D) + " D2: 0x" + Util.toHexStringBE(D2));
- }
- else
- System.out.println("Assumption correct!");
-
- for(int I=NROUNDS-1; I>=0; I--) {
- T=((C+rol(D,11))^Key[I&3]);
- TA=A^substLong(T);
- T=((D^rol(C,17))+Key[I&3]);
- TB=B^substLong(T);
- A=C;
- B=D;
- C=TA;
- D=TB;
- }
-
- if(true) {
- C ^= Key[0];
- Buf[n+0 ]=(byte)(0xFF & C);
- Buf[n+1 ]=(byte)(0xFF & (C>>>8));
- Buf[n+2 ]=(byte)(0xFF & (C>>>16));
- Buf[n+3 ]=(byte)(0xFF & (C>>>24));
- D ^= Key[1];
- Buf[n+4 ]=(byte)(0xFF & D);
- Buf[n+5 ]=(byte)(0xFF & (D>>>8));
- Buf[n+6 ]=(byte)(0xFF & (D>>>16));
- Buf[n+7 ]=(byte)(0xFF & (D>>>24));
- A ^= Key[2];
- Buf[n+8 ]=(byte)(0xFF & A);
- Buf[n+9 ]=(byte)(0xFF & (A>>>8));
- Buf[n+10]=(byte)(0xFF & (A>>>16));
- Buf[n+11]=(byte)(0xFF & (A>>>24));
- B ^= Key[3];
- Buf[n+12]=(byte)(0xFF & B);
- Buf[n+13]=(byte)(0xFF & (B>>>8));
- Buf[n+14]=(byte)(0xFF & (B>>>16));
- Buf[n+15]=(byte)(0xFF & (B>>>24));
- }
- else {
- System.arraycopy(Util.toByteArrayLE(C^Key[0]), 0, Buf, n+0 , 4);
- System.arraycopy(Util.toByteArrayLE(D^Key[1]), 0, Buf, n+4 , 4);
- System.arraycopy(Util.toByteArrayLE(A^Key[2]), 0, Buf, n+8 , 4);
- System.arraycopy(Util.toByteArrayLE(B^Key[3]), 0, Buf, n+12, 4);
- }
-
- UpdKeys(InBuf);
- }
-
-
- /*
- * As we can't use unsigned data types in Java, we'll have to unsign the data
- * every time we use it. Modifications: unsign the usage of Buf[I] by "& 0xFF".
- */
- /**
- * Updates keys. ;)
- * <pre>
- * Global modify set:
- * Key (int[4])
- * Global read set:
- * CRCTab (int[256])
- * Local use set:
- * (in) Buf (byte[])
- * I (int)
- * </pre>
- */
- public void UpdKeys(byte[]/*UBYTE*/ Buf) {
- for(int I=0; I<16; I+=4) {
- Key[0]^=CRCTab[Buf[I] & 0xFF]; /* xxx may be I'll rewrite this */
- Key[1]^=CRCTab[Buf[I+1] & 0xFF]; /* in asm for speedup */
- Key[2]^=CRCTab[Buf[I+2] & 0xFF];
- Key[3]^=CRCTab[Buf[I+3] & 0xFF];
- }
- }
-
- /* Password is supposed to be trimmed to the actual password length and not zero-terminated. */
- /**
- * Sets crypt keys. ;)<br>
- * <code>Password</code> is supposed to be trimmed to the actual
- * password length and not zero-terminated.<p>
- * <pre>
- * Global read set:
- * InitSubstTable (final short[256])
- * CRCTab
- *
- * Global modify set:
- * Key (final int[4])
- * SubstTable (final short[256])
- * In SetOldKeys:
- * OldKey (final short[4])
- * PN1 (byte)
- * PN2 (byte)
- * PN3 (byte)
- *
- * Local use set:
- * Password (byte[])
- * I (int)
- * J (int)
- * K (int)
- * N1 (short)
- * N2 (short)
- * Psw (final byte[256])
- * Ch (short)
- *
- * Call set:
- * SetOldKeys
- * System.arraycopy
- * EncryptBlock
- * </pre>
- */
- public void SetCryptKeys(byte[] Password) {
- /*unsigned int*/ int I,J,K, PswLength;
- /*unsigned char*/ short N1,N2;
- final /*unsigned char*/ byte[] Psw = new byte[256];
-
- /*UBYTE*/ short Ch;
-
- SetOldKeys(Password);
-
- Key[0]=0xD3A3B879; // Removed the L at the end (indicates 32 bits in C, 64 in Java)
- Key[1]=0x3F6D12F7; // -||-
- Key[2]=0x7515A235; // -||-
- Key[3]=0xA4E7F123; // -||-
- //memset(Psw,0,sizeof(Psw)); // Arrays are automatically initialized to 0 in Java.
- System.arraycopy(Password, 0, Psw, 0, (Password.length<Psw.length?Password.length:Psw.length));
- PswLength = Password.length;//strlen(Password);
- System.arraycopy(InitSubstTable, 0, SubstTable, 0, SubstTable.length); // memcpy(SubstTable,InitSubstTable,sizeof(SubstTable));
-
- for (J=0;J<256;J++) {
- for (I=0;I<PswLength;I+=2) {
- N2=/*(unsigned char)*/(byte)CRCTab[((Psw[I+1]&0xFF)+J)&0xFF];
- for (K=1, N1=/*(unsigned char)*/(byte)CRCTab[((Psw[I]&0xFF)-J)&0xFF]; /* I had to add "&& (N1 < 256)", */
- (N1!=N2) && (N1 < 256); /* because the system crashed with */
- N1++, K++) { /* encrypted RARs */
- /* Swap(&SubstTable[N1],&SubstTable[(N1+I+K)&0xFF]); */
- Ch=SubstTable[N1];
- SubstTable[N1]=SubstTable[(N1+I+K)&0xFF];
- SubstTable[(N1+I+K)&0xFF]=Ch;
- }
- }
- }
- byte[] currentPswBuf = new byte[16];
- for (I=0;I<PswLength;I+=16) {
- System.arraycopy(Psw, I, currentPswBuf, 0, 16);
- EncryptBlock(currentPswBuf);
- }
- }
-
- /**
- * Sets old keys. ;)
- * <pre>
- * Global read set:
- * CRCTab (final int[256])
- *
- * Global modify set:
- * OldKey (final short[4])
- * PN1 (byte)
- * PN2 (byte)
- * PN3 (byte)
- *
- * Local use set:
- * (in) Password (byte[])
- * PswCRC (int)
- * Ch (byte)
- *
- * Call set:
- * //CalcCRC32
- * rol
- * </pre>
- */
- private void SetOldKeys(/*char **/byte[] Password) {
- /*UDWORD*/int PswCRC;
- /*UBYTE*/byte Ch;
- crc.reset();
- crc.update(Password);
- PswCRC=(int)crc.getValue();//CalcCRC32(0xFFFFFFFF,/*(UBYTE*)*/Password,0,Util.strlen(Password));
- OldKey[0]=(/*UWORD*/short)PswCRC;
- OldKey[1]=(/*UWORD*/short)(PswCRC>>>16);
- OldKey[2]=OldKey[3]=0;
- PN1=PN2=PN3=0;
- //while ((Ch=*Password)!=0) {
- for(int i = 0; (Ch=Password[i])!=0; ++i) {
- PN1+=Ch;
- PN2^=Ch;
- PN3+=Ch;
- PN3=(/*UBYTE*/byte)rol(PN3,1);
- OldKey[2]^=((/*UWORD*/short)(Ch^CRCTab[Ch]));
- OldKey[3]+=((/*UWORD*/short)(Ch+(CRCTab[Ch]>>>16)));
- //Password++;
- }
- }
-
- /**
- * Initializes the CRC table <code>crcTab</code>, which has to have a length of 256 elements.
- * @param crcTab the array where the initialized CRC table is to be stored
- * @return the same array that was given as input parameter (for convenience)
- */
- static int[] InitCRC(int[] crcTab) {
- int I, J;
- /*UDWORD*/int C;
- for (I=0;I<256;I++) {
- for (C=I,J=0;J<8;J++)
- C=(C & 1)!=0 ? (C>>>1)^0xEDB88320 : (C>>>1);
- crcTab[I]=C;
- }
- return crcTab;
- }
-
-
- /**
- * Calculates the CRC32 checksum from its arguments.
- * <pre>
- * Global read set:
- * CRCTab ([256])
- *
- * Local use set:
- * (in) StartCRC (int)
- * (in) Addr (byte[])
- * (in) offset (int)
- * (in) Size (int)
- * I (int)
- *
- * Purely functional behavior, no side effects.
- * </pre>
- * @return the updated sum
- */
- static int CalcCRC32(int StartCRC, byte[] Addr, int offset, int Size) {
- /*unsigned */int I;
- for (I=offset; I<Size; I++)
- StartCRC = CRCTab[(byte)StartCRC ^ Addr[I]] ^ (StartCRC >>> 8);
- return(StartCRC);
- }
-
- /* No side effects. */
- private static void debug_log(String s) {
- System.err.println("DEBUG: " + s);
- }
-
- /** No side effects (except position in f increasing). */
- private static int tread(RARFileEntryStream f, byte[] buffer, int offset, int length) {
- try {
- return f.read(buffer, offset, length);
- } catch(Exception e) { e.printStackTrace(); return -1; }
- }
-}
-
-/* **************************************************************************
- ****************************************************************************
- ****************************************************************************
- ************************************************************************** */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/* **************************************************************************
- ****************************************************************************
- ****************************************************************************
- ****************************************************************************
- ******* *******
- ******* *******
- ******* *******
- ******* D E B U G F U N C T I O N S *******
- ******* *******
- ******* *******
- ******* *******
- ****************************************************************************
- ****************************************************************************
- ****************************************************************************
- ************************************************************************** */
-// #ifdef _DEBUG_LOG
-
-
-// /* -- global stuff -------------------------------------------------------- */
-// char log_file_name[256]; /* file name for the log file */
-// DWORD debug_start_time; /* starttime of debug */
-// BOOL debug_started = FALSE; /* debug_log writes only if */
-// /* this is TRUE */
-// /* ------------------------------------------------------------------------ */
-
-
-// /* -- global functions ---------------------------------------------------- */
-// void debug_init_proc(char *file_name)
-// /* Create/Rewrite a log file */
-// {
-// FILE *fp;
-// char date[] = __DATE__;
-// char time[] = __TIME__;
-
-// debug_start_time = GetTickCount(); /* get start time */
-// strcpy(log_file_name, file_name); /* save file name */
-
-// if((fp = fopen(log_file_name, CREATETEXT)) != NULL)
-// {
-// debug_started = TRUE; /* enable debug */
-// fprintf(fp, "Debug log of UniquE's RARFileLib\n"\
-// "~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~\n");
-// fprintf(fp, "(executable compiled on %s at %s)\n\n", date, time);
-// fclose(fp);
-// }
-// }
-
-
-// void debug_log_proc(char *text, char *sourcefile, int sourceline)
-// /* add a line to the log file */
-// {
-// FILE *fp;
-
-// if(debug_started == FALSE) return; /* exit if not initialized */
-
-// if((fp = fopen(log_file_name, APPENDTEXT)) != NULL) /* append to logfile */
-
-// {
-// fprintf(fp, " %8u ms (line %u in %s):\n - %s\n",
-// (/*unsigned */int)(GetTickCount() - debug_start_time),
-// sourceline, sourcefile, text);
-// fclose(fp);
-// }
-// }
-
-// /* ------------------------------------------------------------------------ */
-// #endif
-/* **************************************************************************
- ****************************************************************************
- ****************************************************************************
- ************************************************************************** */
-
diff --git a/src/org/catacombae/rarx/FileAttributes.java b/src/org/catacombae/rarx/FileAttributes.java
deleted file mode 100644
index 8e20f2f..0000000
--- a/src/org/catacombae/rarx/FileAttributes.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.io.PrintStream;
-
-public interface FileAttributes {
- public boolean isDirectory();
- public void print(PrintStream ps, String prefix);
- public void printFields(PrintStream ps, String prefix);
-}
diff --git a/src/org/catacombae/rarx/InvalidDataException.java b/src/org/catacombae/rarx/InvalidDataException.java
deleted file mode 100644
index ad0e029..0000000
--- a/src/org/catacombae/rarx/InvalidDataException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-public class InvalidDataException extends RuntimeException {
- private static final long serialVersionUID = 0x2F49A29E49173487L;
- public InvalidDataException(String message) {
- super(message);
- }
-}
-
diff --git a/src/org/catacombae/rarx/Leaf.java b/src/org/catacombae/rarx/Leaf.java
deleted file mode 100644
index 87d7f49..0000000
--- a/src/org/catacombae/rarx/Leaf.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.catacombae.rarx;
-
-public class Leaf<A> extends TreeNode<A> {
- public Leaf(A value) { super(value); }
- public Leaf() { super(); }
-}
-
diff --git a/src/org/catacombae/rarx/ListArchiveContents.java b/src/org/catacombae/rarx/ListArchiveContents.java
deleted file mode 100644
index 7fac0f1..0000000
--- a/src/org/catacombae/rarx/ListArchiveContents.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.util.*;
-import java.io.*;
-import java.security.MessageDigest;
-import java.util.zip.CRC32;
-
-public class ListArchiveContents {
-
- /*
- * Konceptuellt: Vi har en buffer |E4F91...|A81984B....|
- * ^--------^ <- 32 (0x20) bytes,
- */
-
- //public static final byte[] entrySignature = { 0x7C, 0x30, 0x14, 0x30 };
- public static final String BACKSPACE79 = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
- public static final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
- public static final short ENTRY_TYPE_DIR = 0x0010;
- public static final short ENTRY_TYPE_FILE = 0x0020;
- public static void main(String[] args) throws IOException {
- boolean deleteOnError = true; // Change this to be decided by a command line parameter.
- RandomAccessFile raf = new RandomAccessFile(args[0], "r");
- File outDir = null;
- if(args.length > 1)
- outDir = new File(args[1]);
- byte[] buffer = new byte[4096];
- byte[] pre = new byte[0x16];
- byte[] signature = new byte[0x4];
- byte[] post = new byte[0x6];
- byte[] postString = new byte[0x5];
- byte[] staticEntryData = new byte[pre.length+signature.length+
- post.length+postString.length];
- for(int i = 0; i < staticEntryData.length; ++i)
- staticEntryData[i] = 0;
- ArrayList<byte[]> savedEntries = new ArrayList<byte[]>();
- ArrayList<byte[]> dirEntries = new ArrayList<byte[]>();
- ArrayList<byte[]> fileEntries = new ArrayList<byte[]>();
- LinkedList<String> extractedFiles = new LinkedList<String>();
- LinkedList<String> badFiles = new LinkedList<String>();
- LinkedList<String> createErrorFiles = new LinkedList<String>();
- LinkedList<String> badFilesizeFiles = new LinkedList<String>();
- int signatureCount = 0;
- int readAhead = pre.length+4+post.length;
- int bytesRead = raf.read(buffer);//, readAhead, buffer.length-readAhead);
- long totalBytesRead = bytesRead;
- int lastReadPos = bytesRead;
- //bytesRead += readAhead;
- while(raf.getFilePointer() < raf.length()) {
- for(int i = pre.length; i < lastReadPos-(signature.length+post.length); ++i) {
- if(buffer[i+(0x18-0x16)] == 0x14 &&
- //buffer[i+(0x19-0x16)] == 0x30 && // This one is not really common for all rars.
- //buffer[i+(0x16-0x16)] == 0x7c && buffer[i+(0x17-0x16)] == 0x30
- buffer[i+(0x1b-0x16)] == 0 &&
- (buffer[i+(0x1c-0x16)] == 0x20 || buffer[i+(0x1c-0x16)] == 0x10) &&
- buffer[i+(0x1d-0x16)] == 0 &&
- buffer[i+(0x1e-0x16)] == 0 &&
- buffer[i+(0x1f-0x16)] == 0 //&&
- //buffer[i+(0x20-0x16)] == 0
- ) {
-// System.out.println("buffer[i+(0x1b-0x16)] == " + buffer[i+(0x1b-0x16)]);
-// System.out.println("buffer[i+(0x1c-0x16)] == " + buffer[i+(0x1c-0x16)]);
-// System.out.println("buffer[i+(0x1d-0x16)] == " + buffer[i+(0x1d-0x16)]);
-// System.out.println("buffer[i+(0x1e-0x16)] == " + buffer[i+(0x1e-0x16)]);
-// System.out.println("buffer[i+(0x1f-0x16)] == " + buffer[i+(0x1f-0x16)]);
- ++signatureCount;
- System.out.println("File found at position " + ((raf.getFilePointer()-lastReadPos)+i));
- int fileSize = Util.readIntLE(buffer, i-0xf);
- System.out.println(" Size: " + fileSize + " bytes (0x" + Util.toHexStringBE(fileSize) + ")");
- int crc = Util.readIntLE(buffer, i-6);
- System.out.println(" CRC32: 0x" + Util.toHexStringBE(crc));
- int stringSize = Util.readShortLE(buffer, i+4) & 0xFFFF;
- System.out.println(" String size: " + stringSize);
- short fileType = Util.readShortLE(buffer, i+6);
- System.out.println(" Some type: 0x" + Util.toHexStringBE(fileType));
- int difference = i+signature.length+post.length+stringSize+postString.length-lastReadPos;
-
- if(difference > 0) {
- System.out.println("Beginning of string: " + new String(buffer, i+signature.length+post.length, stringSize-(difference-postString.length), "US-ASCII"));
-// System.out.println(" i=" + i + " post.length=" + post.length + " bytesRead=" + bytesRead);
-// System.out.println(" String size: " + Util.toHexStringBE(stringSize) + " Difference: " + Util.toHexStringBE(difference));
- byte[] diffArray = new byte[difference];
- int tempBytesRead = raf.read(diffArray);
-// System.out.println(" Contents of diffarray: " + new String(diffArray, "US-ASCII"));
- if(tempBytesRead != diffArray.length)
- throw new RuntimeException("Read error."); // Orka..
- totalBytesRead += tempBytesRead;
-
- System.arraycopy(buffer, difference, buffer, 0, lastReadPos-difference);
- System.arraycopy(diffArray, 0, buffer, lastReadPos-difference, diffArray.length);
- i -= difference;
-// System.out.println(" After stringshift: " + new String(buffer, i+4+post.length, stringSize-difference, "US-ASCII"));
-// System.out.println(" " + new String(buffer, i+4+post.length, stringSize, "US-ASCII"));
- }
-
- // Save the data for future analysis
- byte[] data = new byte[staticEntryData.length];
- System.arraycopy(buffer, i-pre.length, data, 0, pre.length+signature.length+post.length);
- System.arraycopy(buffer, i+signature.length+post.length+stringSize, data, pre.length+signature.length+post.length, postString.length);
- savedEntries.add(data);
-
- try {
- /*
- javax.swing.JFrame jf = new javax.swing.JFrame();
- javax.swing.JTextArea tf = new javax.swing.JTextArea(80, 50);
- tf.setFont(new java.awt.Font("Monospaced", java.awt.Font.PLAIN, 12));
- jf.add(new javax.swing.JScrollPane(tf));
- jf.pack();
- jf.setVisible(true);
- for(String charset : java.nio.charset.Charset.availableCharsets().keySet())
- tf.append("Name: \"" + new String(buffer, i+4+post.length, stringSize, charset) + "\" in charset: " + charset + "\n");
- if(true)
- return;
- */
-
- String fullFilename = new String(buffer, i+4+post.length, stringSize, "IBM437");
- String[] filenameComponents = fullFilename.split("\0");
- String filename = filenameComponents[0];
- System.out.println(" Name: \"" + filename + "\"");
- //stdin.readLine();
- System.out.println(" In hex: 0x" + Util.byteArrayToHexString(buffer, i+4+post.length, stringSize));
- if(fileType == ENTRY_TYPE_DIR) {
- System.err.println("Assuming to be dir: " + filename);
- dirEntries.add(data);
- }
-// else if(fileSize == 0 || crc == 0 || filename.split("\\.").length == 2) {
-// System.err.println("Suspicious non-10 dir found: " + filename);
-// System.err.println(" fileSize=" + fileSize);
-// System.err.println(" crc=" + crc);
-// System.err.println(" dots in name: " + (filename.split("\\.").length-1));
-// }
- if(fileType == ENTRY_TYPE_FILE)
- fileEntries.add(data);
-
- if(fileType != ENTRY_TYPE_DIR && fileType != ENTRY_TYPE_FILE) {
- System.err.println("NEW fileType FOUND: 0x" + Util.toHexStringBE(fileType));
- stdin.readLine();
- }
- //System.err.println(" " + filename.split("\\.").length);
- if(difference > 0)
- System.out.println(" (array extended)");
- else
- System.out.println();
-
- if(fileType == ENTRY_TYPE_FILE && outDir != null && fileSize != 0 && crc != 0) {
- File outFile = new File(outDir, filename);
- File outParent = outFile.getParentFile();
- if(outParent != null && ((outParent.exists() && outParent.isDirectory()) ||
- outParent.mkdirs())) {
- int seekIndexInBuffer = i+signature.length+post.length+stringSize+0x5;
- long seekPosition = (raf.getFilePointer()-lastReadPos)+seekIndexInBuffer;
- if(seekPosition+fileSize > raf.length()) {
- System.out.println("ERROR: Invalid file size for \"" + filename + "\" (" + fileSize + " bytes)");
- badFilesizeFiles.add(filename);
- }
- else {
- RandomAccessFile outRaf = new RandomAccessFile(outFile, "rw");
- System.out.println("input.getFilePointer() = " + raf.getFilePointer());
- System.out.println("readAhead = " + (readAhead));
- System.out.println("bytesRead = "+ bytesRead);
- System.out.println("lastReadPos = "+ lastReadPos);
- System.out.println("i = " + i);
- byte[] mycrc32 = copyData(raf, seekPosition, outRaf, 0, fileSize);
- outRaf.close();
- System.out.println("Their digest: 0x" + Util.toHexStringBE(crc));
- System.out.println("My digest : 0x" + Util.byteArrayToHexString(mycrc32));
- //stdin.readLine();
- if(Util.arraysEqual(Util.toByteArrayBE(crc), mycrc32)) {
- System.out.println("Digests are equal.");
- extractedFiles.addLast(filename);
- /* H�r b�r vi flytta fram filpekaren till precis efter den extraherade filen,
- f�r att undvika att titta i rar filer som �r lagrade inuti andra rar-filer,
- samt f�r att snabba upp extraheringen. */
- long oldFilePointer = raf.getFilePointer();
- long newFilePointer = seekPosition+fileSize-readAhead;
- if(newFilePointer > oldFilePointer) {
- raf.seek(newFilePointer);
- bytesRead = raf.read(buffer);
- lastReadPos = bytesRead;
- totalBytesRead += (raf.getFilePointer() - oldFilePointer);
- i = pre.length;
- }
- else {
- System.out.print("Situation where newFilePointer <= oldFilePointer har occurred!");
- //stdin.readLine();
- }
- }
- else {
- System.out.println("NOT EQUAL! :(:(:(:(");
- if(deleteOnError) {
- while(!outFile.delete()) {
- System.out.print("Could not delete file \"" + outFile + "\" try again (y/n)? ");
- String answer = stdin.readLine();
- while(!(answer.trim().equalsIgnoreCase("y") || answer.trim().equalsIgnoreCase("n"))) {
- System.out.print("Ivalid answer. Answer again: (y/n)? ");
- answer = stdin.readLine();
- }
-
- if(answer.trim().equalsIgnoreCase("n"))
- break;
- }
- }
- badFiles.addLast(filename);
- //stdin.readLine();
- }
- }
- //stdin.readLine();
- }
- else {
- System.out.println("Failed to create \"" + outFile + "\"");
- createErrorFiles.addLast(filename);
- }
- }
- } catch(Exception e) {
- e.printStackTrace();
- String answer;
- do {
- System.out.print("Do you want to continue (y/n)? ");
- answer = stdin.readLine();
- } while(!(answer.trim().equalsIgnoreCase("y") || answer.trim().equalsIgnoreCase("n")));
-
- if(answer.trim().equalsIgnoreCase("n"))
- System.exit(0);
- }
- }
- }
- /* Vi vill nu flytta (readAhead) bytes data fr�n slutet av den fyllda delen av arrayen till b�rjan. */
- System.arraycopy(buffer, lastReadPos-readAhead, buffer, 0, readAhead);
-
- /* L�s in nya data i arrayen, men skriv inte �ver dess inledande (readAhead) bytes */
- bytesRead = raf.read(buffer, readAhead, buffer.length-readAhead);
- totalBytesRead += bytesRead;
- lastReadPos = readAhead+bytesRead;
- }
- System.out.println();
- System.err.println("Found " + signatureCount + " signatures.");
- System.err.println("Found " + savedEntries.size() + " entries.");
- if(savedEntries.size() > 0) {
- System.err.println("Running analysis on all entries...");
- Region[] similarRegions = findSimilarities(savedEntries);
- byte[] entry = savedEntries.get(0);
- System.out.println("First entry: 0x" + Util.byteArrayToHexString(entry));
- LinkedList<byte[]> regionData = new LinkedList<byte[]>();
- for(Region r : similarRegions) {
- byte[] currentRegion = new byte[(int)((r.endOffset+1)-r.startOffset)];
- System.arraycopy(entry, (int)r.startOffset, currentRegion, 0, currentRegion.length);
- System.out.println(r + ": 0x" + Util.byteArrayToHexString(currentRegion));
- regionData.addLast(currentRegion);
- }
- }
- if(dirEntries.size() > 0) {
- System.err.println("Running analysis on directories only...");
- Region[] similarRegions = findSimilarities(dirEntries);
- byte[] entry = dirEntries.get(0);
- LinkedList<byte[]> regionData = new LinkedList<byte[]>();
- for(Region r : similarRegions) {
- byte[] currentRegion = new byte[(int)((r.endOffset+1)-r.startOffset)];
- System.arraycopy(entry, (int)r.startOffset, currentRegion, 0, currentRegion.length);
- System.out.println(r + ": 0x" + Util.byteArrayToHexString(currentRegion));
- regionData.addLast(currentRegion);
- }
- }
- if(fileEntries.size() > 0) {
- System.err.println("Running analysis on files only...");
- Region[] similarRegions = findSimilarities(fileEntries);
- byte[] entry = fileEntries.get(0);
- LinkedList<byte[]> regionData = new LinkedList<byte[]>();
- for(Region r : similarRegions) {
- byte[] currentRegion = new byte[(int)((r.endOffset+1)-r.startOffset)];
- System.arraycopy(entry, (int)r.startOffset, currentRegion, 0, currentRegion.length);
- System.out.println(r + ": 0x" + Util.byteArrayToHexString(currentRegion));
- regionData.addLast(currentRegion);
- }
- }
-
- if(badFiles.size() > 0) {
- System.out.println("The following " + badFiles.size() + " files failed the CRC-32 checksum test" + (deleteOnError?" and were not extracted":"") + ":");
- for(String filename : badFiles)
- System.out.println(" \"" + filename + "\"");
- }
- if(badFilesizeFiles.size() > 0) {
- System.out.println("The following " + badFilesizeFiles.size() + " files could not be extracted due to incorrectly specified file size:");
- for(String filename : badFilesizeFiles)
- System.out.println(" \"" + filename + "\"");
- }
- if(createErrorFiles.size() > 0) {
- System.out.println("The following " + createErrorFiles.size() + " files could not be created:");
- for(String filename : createErrorFiles)
- System.out.println(" \"" + filename + "\"");
- }
-
- System.out.println("Read " + totalBytesRead + " bytes from input file.");
- }
-
- /** Returns the calculated CRC-32 checksum of the copied data. */
- public static byte[] copyData(RandomAccessFile input, long inputPos, RandomAccessFile output, long outputPos, long fileSize) throws IOException {
- CRC32 crc32Digest = new CRC32();//MessageDigest.getInstance("CRC32");
- long oldFilePointer = input.getFilePointer();
- byte[] otherBuffer = new byte[4096];
- input.seek(inputPos);
- System.out.println("Seeking to " + input.getFilePointer() + ".");
- int totalBytesRead2 = 0;
- System.out.println("otherBuffer.length="+otherBuffer.length+" fileSize="+fileSize+" totalBytesRead2="+totalBytesRead2);
- System.out.println("input.read("+otherBuffer+", "+0+", " + (totalBytesRead2+otherBuffer.length<fileSize?otherBuffer.length:fileSize-totalBytesRead2) + ");");
- int bytesRead2 = input.read(otherBuffer, 0, (totalBytesRead2+otherBuffer.length<fileSize?otherBuffer.length:(int)(fileSize-totalBytesRead2)));
- totalBytesRead2 += bytesRead2;
- while(totalBytesRead2 < fileSize) {
- crc32Digest.update(otherBuffer, 0, bytesRead2);
- output.write(otherBuffer, 0, bytesRead2);
- bytesRead2 = input.read(otherBuffer, 0, (totalBytesRead2+otherBuffer.length<fileSize?otherBuffer.length:(int)(fileSize-totalBytesRead2)));
- totalBytesRead2 += bytesRead2;
- }
-
- crc32Digest.update(otherBuffer, 0, bytesRead2);
- output.write(otherBuffer, 0, bytesRead2);
- System.out.println("Extracted contents!");// Check them and press enter...");
- input.seek(oldFilePointer);
- return Util.toByteArrayBE((int)(crc32Digest.getValue() & 0xFFFFFFFF));
- }
- public static Region[] findSimilarities(List<byte[]> arrays) throws IOException {
- if(arrays.size() < 1)
- return new Region[0];
-
- long minLength = Long.MAX_VALUE;
- boolean differentLengths = false;
- for(byte[] currentData : arrays) {
- if(currentData.length < minLength) {
- if(minLength != Long.MAX_VALUE)
- differentLengths = true;
- minLength = currentData.length;
- }
- }
- if(differentLengths)
- System.err.println("WARNING: Input arrays are not of equal length...");
-
- LinkedList<Region> regions = new LinkedList<Region>();
-
- long regionStart = -1;
- for(int i = 0; i < minLength; ++i) {
- int lastByte = -1;
- int[] values = new int[arrays.size()];
- for(int j = 0; j < arrays.size(); ++j)
- values[j] = arrays.get(j)[i];//files[j].read();
-
- for(int currentByte : values) {
- //System.out.print("0x" + Integer.toHexString(currentByte) + " == ");
- if(lastByte == -1)
- lastByte = currentByte;
- else if(currentByte != lastByte) {
- lastByte = -1;
- //System.out.println("FALSE");
- break;
- }
- }
-// if(lastByte != -1)
-// System.out.println("TRUE");
- if(lastByte == -1 && regionStart != -1) {
- //System.out.println("Region concluded at 0x" + Long.toHexString(i));
- regions.add(new Region(regionStart, i-1));
- regionStart = -1;
- }
- else if(lastByte != -1 && regionStart == -1) {
- //System.out.println("New region started at 0x" + Long.toHexString(i));
- regionStart = i;
- }
- }
-
- System.out.println("Found " + regions.size() + " similar regions.");
- long totalSimilarBytes = 0;
- for(Region r : regions) {
- long regionLength = r.endOffset-r.startOffset+1;
- System.out.println(" 0x" + Long.toHexString(r.startOffset) + "-0x" + Long.toHexString(r.endOffset) + " (" + regionLength + " B)");
- totalSimilarBytes += regionLength;
- }
- System.out.println("Total matching bytes: " + totalSimilarBytes);
- return regions.toArray(new Region[regions.size()]);
- }
-
- private static class Region {
- public long startOffset;
- public long endOffset;
-
- public Region(long startOffset, long endOffset) {
- this.startOffset = startOffset;
- this.endOffset = endOffset;
- }
- }
-}
-
-class TestModel {
- public static void main(String[] args) {
- byte[] buffer = new byte[4096];
- int readAhead = 32;
- fill(buffer);
- while(true) {
- for(int i = 0; i < buffer.length-readAhead; ++i) {
-
- }
-
- // Vi har g�tt igenom buffer fr�n 0 till n-readAhead
- // Kopiera d� readAhead bytes fr�n slutet till b�rjan och fyll
- System.arraycopy(buffer, buffer.length-readAhead, buffer, 0, readAhead);
- fill(buffer, readAhead, buffer.length-readAhead);
- }
- }
-
- public static int alternate(byte[] buffer) {
- fill(buffer);
- while(true) {
- for(int i = 0; i < buffer.length; ++i)
- dosomething(buffer[i]);
- fill(buffer);
- }
- }
-
- public static void fill(byte[] buffer) {}
- public static void fill(byte[] buffer, int i, int j) {}
- public static void dosomething(byte b) {}
-}
diff --git a/src/org/catacombae/rarx/ListFilesInArchive.java b/src/org/catacombae/rarx/ListFilesInArchive.java
deleted file mode 100644
index 1f04825..0000000
--- a/src/org/catacombae/rarx/ListFilesInArchive.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.util.*;
-import java.io.*;
-
-public class ListFilesInArchive {
- public static void main(String[] args) {
- try {
- File f = new File(args[0]);
- RARFileEntry[] entries = listFiles(f);
- for(RARFileEntry entry : entries) {
- NewFileHeader nfh = entry.getHeader(0);
- System.out.println(nfh.getFilenameAsString());
- }
- } catch(InvalidDataException e) {
- System.out.println("Invalid RAR-file. Message: " + e.getMessage());
- System.out.println("File: \"" + args[0] + "\"");
- } catch(IOException ioe) {
- ioe.printStackTrace();
- }
- }
-
- public static Tree<RARFileEntry> listFilesAsTree(File rarFile) throws IOException, InvalidDataException {
- return listFilesAsTree(rarFile, false);
- }
- public static Tree<RARFileEntry> listFilesAsTree(File rarFile, boolean includeComments) throws IOException, InvalidDataException {
- RARFileEntry[] contents = listFiles(rarFile, includeComments);
-
- // Create the empty directory tree
- Tree<RARFileEntry> rarTree = new Tree<RARFileEntry>();
- for(RARFileEntry currentEntry : contents) {
- NewFileHeader nfh = currentEntry.getHeader(0);
-
- String[] filenameComponents = nfh.getFilenameAsString().split("\\" + NewFileHeader.PATH_SEPARATOR);
- Tree<RARFileEntry> currentNode = rarTree;
-
- // Loop through the first n-1 components and create tree entries when needed
- for(int i = 0; i < filenameComponents.length-1; ++i) {
- TreeNode<RARFileEntry> childNode = currentNode.get(filenameComponents[i]);
- if(childNode == null) {
- childNode = new Tree<RARFileEntry>();
- currentNode.put(filenameComponents[i], childNode);
- }
-
- if(childNode instanceof Tree)
- currentNode = (Tree<RARFileEntry>)childNode;
- else
- throw new RuntimeException("Duplicate entries in RAR file");
- }
-
- // The last component is mapped to the current RARFileEntry
- TreeNode<RARFileEntry> childNode = currentNode.get(filenameComponents[filenameComponents.length-1]);
- if(childNode == null) {
- if(nfh.getFileAttributesStructured().isDirectory())
- childNode = new Tree<RARFileEntry>(currentEntry);
- else
- childNode = new Leaf<RARFileEntry>(currentEntry);
- currentNode.put(filenameComponents[filenameComponents.length-1], childNode);
- }
- else if(nfh.getFileAttributesStructured().isDirectory()) {
- if(childNode.getValue() == null)
- childNode.setValue(currentEntry);
- else
- throw new RuntimeException("Duplicate entries in RAR file");
- }
- else
- throw new RuntimeException("Duplicate entries in RAR file");
- }
-
- // Should probably check that the directory structure is complete before passing it on
-
- return rarTree;
- }
-
-
- public static RARFileEntry[] listFiles(File rarFile) throws IOException, InvalidDataException {
- return listFiles(rarFile, false);
- }
- public static RARFileEntry[] listFiles(File rarFile, boolean includeComments) throws IOException, InvalidDataException {
- LinkedList<RARFileEntry> entries = new LinkedList<RARFileEntry>();
- RARFileEntry outgoingEntry = null;
- mainLoop:
- do {
- //outgoingEntry = null;
- RandomAccessFile raf = new RandomAccessFile(rarFile, "r");
-
- RARFile.readMarkHeader(raf);
- //NewMainArchiveHeader nmah = RARFile.readNewMainArchiveHeader(raf);
- //nmah.print(System.out, "");
- long offset = raf.getFilePointer();
- RARHeader rh = RARFile.readHeader(raf);
- while(rh != null) {
- try {
- if(rh instanceof NewFileHeader && (includeComments || !(rh instanceof CommentHeader))) {
- NewFileHeader nfh = (NewFileHeader)rh;
- if(!nfh.hasIncomingData()) {
- RARFileEntry rfe = new RARFileEntry(rarFile, offset, nfh);
- if(outgoingEntry != null && nfh.hasOutgoingData()) {
- throw new RuntimeException("Found two outgoing files in the same archive!");
- }
- else if(nfh.hasOutgoingData())
- outgoingEntry = rfe;
-
- entries.add(rfe);
- }
- else {
- if(outgoingEntry != null) {
- outgoingEntry.addPart(rarFile, offset, nfh);
- if(!nfh.hasOutgoingData())
- outgoingEntry = null;
- }
- else {
- // Reading incomplete entry.
- RARFileEntry rfe = new RARFileEntry(rarFile, offset, nfh);
- entries.add(rfe);
- if(nfh.hasOutgoingData())
- outgoingEntry = rfe;
- }
- }
- /*
- if(!nfh.hasIncomingData())
- entries.add(nfh);
- if(nfh.hasOutgoingData()) {
- if(outgoingEntry == null)
- outgoingEntry = nfh;
- else
- throw new RuntimeException("Found two outgoing files in the same archive!");
- }
- */
- //nfh.print(System.out, "");
- }
- offset = raf.getFilePointer();
- rh = RARFile.readHeader(raf);
- } catch(IOException ioe) {
- ioe.printStackTrace();
- break mainLoop;
- }
- }
- if(outgoingEntry != null) {
- File oldRarFile = rarFile;
- rarFile = RARFileEntryStream.getNextFile(rarFile);
- if(rarFile == null)
- throw new FileNotFoundException("Could not find successor to \"" + oldRarFile + "\"");
-// long posInNextFile = RARFileEntryStream.getMatchingPosInFile(nextFile, nfh);
-// if(posInNextFile == -1)
-// throw new FileNotFoundException();
-// getSegments(nextFile, posInNextFile, list, true);
- }
- } while(outgoingEntry != null);
-
- return entries.toArray(new RARFileEntry[entries.size()]);
- }
-}
diff --git a/src/org/catacombae/rarx/ListRecursive.java b/src/org/catacombae/rarx/ListRecursive.java
deleted file mode 100644
index a0d34d8..0000000
--- a/src/org/catacombae/rarx/ListRecursive.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.io.*;
-import java.util.regex.Pattern;
-
-public class ListRecursive {
- public static class RegexpFileFilter implements FileFilter {
- private String pattern;
- public RegexpFileFilter(String pattern) {
- this.pattern = pattern;
- }
- public boolean accept(File f) {
- return Pattern.matches(pattern, f.getName());
- }
- }
-
- public static void main(String[] args) throws IOException {
- File rootDir = null;
- String pattern = null;
- File outFile = null;
- System.out.println("args.length=" + args.length);
- if(args.length > 2) {
- rootDir = new File(args[0]);
- pattern = args[1];
- outFile = new File(args[2]);
- System.out.println("Writing to file " + outFile.getCanonicalPath());
- }
- else if(args.length > 1) {
- rootDir = new File(args[0]);
- pattern = args[1];
- }
- else if(args.length > 0)
- pattern = args[0];
- else {
- System.out.println("Could not parse arguments.");
- return;
- }
-
- if(rootDir == null)
- rootDir = new File(System.getProperty("user.dir"));
-
- FileFilter fnf;
- if(pattern == null)
- fnf = null;
- else
- fnf = new RegexpFileFilter(pattern);
-
- if(outFile == null)
- listRecursive(rootDir, fnf, System.out);
- else
- listRecursive(rootDir, fnf, new PrintStream(new FileOutputStream(outFile), false, "UTF-8"));
- }
-
- public static void listRecursive(File rootDir, FileFilter fnf, PrintStream ps) {
- File[] allChildren = rootDir.listFiles();
- File[] matchingChildren;
- if(fnf == null)
- matchingChildren = allChildren;
- else
- matchingChildren = rootDir.listFiles(fnf);
-
- if(matchingChildren != null) {
- for(File child : matchingChildren)
- ps.println(child);
- }
-
- if(allChildren != null) {
- for(File child : allChildren)
- listRecursive(child, fnf, ps);
- }
- }
-}
diff --git a/src/org/catacombae/rarx/MarkHeader.java b/src/org/catacombae/rarx/MarkHeader.java
deleted file mode 100644
index 76c17ef..0000000
--- a/src/org/catacombae/rarx/MarkHeader.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-public class MarkHeader extends RARHeader {
- private static final byte[] oldRarHeader = { 0x52, 0x45, 0x7e, 0x5e };
- private static final byte[] rar2Header = { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 };
- private static final byte[] uniqueHeader = { 0x55, 0x6e, 0x69, 0x71, 0x75, 0x45, 0x21 }; // "UniquE!" in ASCII
-
- public MarkHeader(byte[] data, int offset) {
- super(data, offset);
- validateData();
- }
-
- protected void validateData() {
- byte[] mark = getHeaderData();
- if(Util.arraysEqual(Util.createCopy(mark, 0, 4), oldRarHeader)) {
- throw new InvalidDataException("An older, unsupported RAR format was detected.");
- }
- else {
- /* original RAR v2.0 */
- if(Util.arraysEqual(mark, rar2Header) ||
- Util.arraysEqual(mark, uniqueHeader)) {
-
- }
- else
- throw new InvalidDataException("Not a RAR file.");
- }
- }
-}
diff --git a/src/org/catacombae/rarx/NewFileHeader.java b/src/org/catacombae/rarx/NewFileHeader.java
deleted file mode 100644
index 104bed1..0000000
--- a/src/org/catacombae/rarx/NewFileHeader.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.util.LinkedList;
-import java.util.Iterator;
-import java.util.Calendar;
-import java.util.Date;
-import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
-
-public class NewFileHeader extends RARHeader {
- /*
- * struct NewFileHeader
- * size: 32 bytes
- *
- * BP Size Description
- * 0 2 HeadCRC
- * 2 1 HeadType
- * 3 2 Flags
- * 5 2 HeadSize
- * 7 4 PackSize
- * 11 4 UnpSize
- * 15 1 HostOS
- * 16 4 FileCRC
- * 20 4 FileTime
- * 24 1 UnpVer
- * 25 1 Method
- * 26 2 NameSize
- * 28 4 FileAttr
- */
-
- // Possible values for the hostOS field in NewFileHeader, and possibly elsewhere...
- public static final int HOSTOS_MS_DOS = 0;
- public static final int HOSTOS_OS2 = 1;
- public static final int HOSTOS_WIN_32 = 2;
- public static final int HOSTOS_UNIX = 3;
- public static final String[] hostOSStrings = { "MS-DOS", "OS/2", "Win32", "UNIX" };
-
- public static final int FM_NORMAL = 0x00;
- public static final int FM_RDONLY = 0x01;
- public static final int FM_HIDDEN = 0x02;
- public static final int FM_SYSTEM = 0x04;
- public static final int FM_LABEL = 0x08;
- public static final int FM_DIREC = 0x10;
- public static final int FM_ARCH = 0x20;
-
- public static final String PATH_SEPARATOR = "\\";
-
- private final byte[] packSize = new byte[4];
- private final byte[] unpSize = new byte[4];
- private final byte[] hostOS = new byte[1];
- private final byte[] fileCRC = new byte[4];
- private final byte[] fileTime = new byte[4];
- private final byte[] unpVer = new byte[1];
- private final byte[] method = new byte[1];
- private final byte[] nameSize = new byte[2];
- private final byte[] fileAttr = new byte[4];
- private final byte[] packSizeExtended;
- private final byte[] unpSizeExtended;
- private final byte[] filename;
- private final byte[] trailingData;
-
- public NewFileHeader(byte[] data, int offset) {
- super(data, offset);
- System.arraycopy(data, offset+7, packSize, 0, 4);
- System.arraycopy(data, offset+11, unpSize, 0, 4);
- System.arraycopy(data, offset+15, hostOS, 0, 1);
- System.arraycopy(data, offset+16, fileCRC, 0, 4);
- System.arraycopy(data, offset+20, fileTime, 0, 4);
- System.arraycopy(data, offset+24, unpVer, 0, 1);
- System.arraycopy(data, offset+25, method, 0, 1);
- System.arraycopy(data, offset+26, nameSize, 0, 2);
- System.arraycopy(data, offset+28, fileAttr, 0, 4);
- if(hasExtendedHeader()) {
- packSizeExtended = new byte[4];
- unpSizeExtended = new byte[4];
- System.arraycopy(data, offset+32, packSizeExtended, 0, 4);
- System.arraycopy(data, offset+36, unpSizeExtended, 0, 4);
- }
- else {
- packSizeExtended = new byte[0];
- unpSizeExtended = new byte[0];
- }
- final int extSize = packSizeExtended.length + unpSizeExtended.length;
- filename = new byte[getNameSize()];
- trailingData = new byte[getHeadSize()-(getStaticSize()+extSize+filename.length)];
- System.arraycopy(data, offset+32+extSize, filename, 0, filename.length);
- System.arraycopy(data, offset+32+extSize+filename.length, trailingData, 0, trailingData.length);
- validateData();
- }
-
- public static int getStaticSize() { return 32; }
- public int getSize() { return _getSize(); }
- private int _getSize() { return getHeadSize(); }
-
- protected void validateData() {
- //print(System.out, "");
- super.validateData();
- if(getHeadType() != FILE_HEAD)
- throw new InvalidDataException("Incorrect head type! (headType=" + getHeadType() + ")");
- if(getHeadSize() < getStaticSize())
- throw new InvalidDataException("Invalid size! (size=" + getHeadSize() + ")");
- if(getHostOSAsString() == null)
- throw new InvalidDataException("Host OS value invalid.");
- }
-
- public long getPackSize() {
- long result = Util.readIntLE(packSize) & 0xFFFFFFFFL;
- if(packSizeExtended.length == 4)
- result |= (Util.readIntLE(packSizeExtended) & 0xFFFFFFFFL) << 32;
- return result;
- }
- public long getUnpSize() {
- long result = Util.readIntLE(unpSize) & 0xFFFFFFFFL;
- if(unpSizeExtended.length == 4)
- result |= (Util.readIntLE(unpSizeExtended) & 0xFFFFFFFFL) << 32;
- return result;
-// if(unpSizeExtended.length == 4) {
-// return Util.readIntLE(unpSize);
- }
- public byte getHostOS() { return Util.readByteLE(hostOS); }
- public int getFileCRC() { return Util.readIntLE(fileCRC); }
- public int getFileTime() { return Util.readIntLE(fileTime); }
- public byte getUnpVer() { return Util.readByteLE(unpVer); }
- public byte getMethod() { return Util.readByteLE(method); }
- public short getNameSize() { return Util.readShortLE(nameSize); }
- public int getFileAttr() { return Util.readIntLE(fileAttr); }
- public byte[] getFilename() { return Util.createCopy(filename); }
- public byte[] getTrailingData() { return Util.createCopy(trailingData); }
-
- public byte[] getHeaderData() {
- byte[] data = new byte[_getSize()];
- System.arraycopy(super.getHeaderData(), 0, data, 0, super.getSize());
- System.arraycopy(packSize, 0, data, 7, packSize.length);
- System.arraycopy(unpSize, 0, data, 11, unpSize.length);
- System.arraycopy(hostOS, 0, data, 15, hostOS.length);
- System.arraycopy(fileCRC, 0, data, 16, fileCRC.length);
- System.arraycopy(fileTime, 0, data, 20, fileTime.length);
- System.arraycopy(unpVer, 0, data, 24, unpVer.length);
- System.arraycopy(method, 0, data, 25, method.length);
- System.arraycopy(nameSize, 0, data, 26, nameSize.length);
- System.arraycopy(fileAttr, 0, data, 28, fileAttr.length);
- if(hasExtendedHeader()) {
- System.arraycopy(packSizeExtended, 0, data, 32, 4);
- System.arraycopy(unpSizeExtended, 0, data, 36, 4);
- }
- final int extSize = packSizeExtended.length + unpSizeExtended.length;
- System.arraycopy(filename, 0, data, 32+extSize, filename.length);
- System.arraycopy(trailingData, 0, data, 32+extSize+filename.length, trailingData.length);
- return data;
- }
-
- /**
- * true if the header is 40 bytes long, false if it is 32 bytes long
- * The 40 byte header exists to accommodate filesizes > 2^32
- */
- public boolean hasExtendedHeader() {
- return getFlag(8);
- }
-
- /**
- * true if this file is a continuation of a previous file (split archive)
- */
- public boolean hasIncomingData() {
- return getFlag(0);
- }
-
- /**
- * true if this file continues in another file (split archive)
- */
- public boolean hasOutgoingData() {
- return getFlag(1);
- }
-
- public Date getFileTimeAsDate() {
- int data = getFileTime();
- int year = 1980 + ((data >> (4+5+5+6+5)) & 0x7F);
- int month = ((data >> (5+5+6+5)) & 0xF)-1;
- int day = (data >> (5+6+5)) & 0x1F;
- int hour = (data >> (6+5)) & 0x1F;
- int minute = (data >> (5)) & 0x3F;
- int doublesecond = data & 0x1F; // the archive format only supports 2-second precision (probably due to simpler design)
-
-// System.out.println("year = " + year);
-// System.out.println("month = " + month);
-// System.out.println("day = " + day);
-// System.out.println("hour = " + hour);
-// System.out.println("minute = " + minute);
-// System.out.println("doublesecond = " + doublesecond);
-
- Calendar c = Calendar.getInstance();
- c.setTime(new Date(0));
- c.set(Calendar.YEAR, year);
- c.set(Calendar.MONTH, month);
- c.set(Calendar.DAY_OF_MONTH, day);
- c.set(Calendar.HOUR, hour);
- c.set(Calendar.MINUTE, minute);
- c.set(Calendar.SECOND, doublesecond*2);
- return c.getTime();
- }
-
- public FileAttributes getFileAttributesStructured() {
- byte hostOS = getHostOS();
- if(hostOS == HOSTOS_WIN_32)
- return new Win32FileAttributes(getFileAttr());
- else if(hostOS == HOSTOS_UNIX)
- return new UNIXFileAttributes(getFileAttr());
- else if(hostOS == HOSTOS_MS_DOS || hostOS == HOSTOS_OS2)
- return new Win32FileAttributes(getFileAttr()); // Win, DOS and OS/2 seems to have a lot in common, but I don't really know what the file attributes will look like under DOS and OS/2. Hopefully something like the Win32-attributes (:
- else
- throw new RuntimeException("Unknown OS type!");
- }
-
-// public boolean isFile() {
-// return getFlag(getFileAttr(), 13);
-// }
-
- public String getHostOSAsString() {
- return hostOSToString(getHostOS());
- }
-
- public String getUnpackVersionAsString() {
- byte unpVer = getUnpVer();
- return (unpVer/10) + "." + (unpVer%10);
- }
-
- public String getFilenameAsString() {
- String result = getUnicodeFilenameAsString();
- if(result == null)
- result = getLegacyFilenameAsString();
- return result;
- }
- public String getLegacyFilenameAsString() {
- /* After testing, it seems that one of the old MS-DOS charsets
- are used to store the file name in this structure. If
- different charsets are supported, I don't know how to detect
- which charset will be used yet. Code Page 850 is used for now. */
- try {
- return new String(filename, /*"IBM437"*/"iso-8859-1").split("\0")[0];
- } catch(UnsupportedEncodingException uee) {
- throw new RuntimeException(uee);
- }
- }
-
- public String getUnicodeFilenameAsString() {
- /* To cope with characters outside the old IBM charset originally
- used for filenames, RAR embeds extra data after the area
- containing the IBM charset filename. The old style filename is
- terminated by null, and after that follows the characters that
- could not be encoded properly with the IBM charset. */
- boolean debug = false;
- if(debug) System.out.println("getExtendedCharsetFilenameAsString();");
- char[] legacyFilename = getLegacyFilenameAsString().toCharArray();
- char[] unicodeFilename = new char[legacyFilename.length];
- int unicodeFilenamePointer = 0;
- //LinkedList<Character> codeUnitList = new LinkedList<Character>();
-
- // Find the index at which the extended filename characters begin (first occurrence of 0x00).
- int zeroIndex = 0;
- for(; zeroIndex < filename.length; ++zeroIndex)
- if(filename[zeroIndex] == 0)
- break;
-
- int codeUnitsRead = 0;;
-
- int extendedDataPointer = zeroIndex+1;
- if(extendedDataPointer+2 >= filename.length) // Must have compressedLSB (1 bytes) and at least one byte
- return null;
- byte compressedLSB = Util.readByteLE(filename, extendedDataPointer++);
-
- mainLoop:
- while(extendedDataPointer < filename.length) {
- if(debug) System.out.println(" Reading 4 bytes... (found " + codeUnitsRead +
- " code points, extendedDataPointer=" + extendedDataPointer + ")");
- byte groupDescriptor = Util.readByteLE(filename, extendedDataPointer++);
- for(int i = 0; (i < 4) && (extendedDataPointer < filename.length); ++i) {
- byte current = (byte)((groupDescriptor >>> ((3-i)*2)) & 0x3); // 0b11
- if(current == 0x0) { // 0b00
- //if(extendedDataPointer >= filename.length) break;
- char codeUnit = (char)(Util.readByteLE(filename, extendedDataPointer++) & 0xFF);
- if(debug) System.out.println(" Encountered 8-bit character: 0x" + Util.toHexStringBE(codeUnit));
- //codeUnitList.add(codeUnit);
- unicodeFilename[unicodeFilenamePointer++] = codeUnit;
- ++codeUnitsRead;
- }
- else if(current == 0x1) {
- //if(extendedDataPointer >= filename.length) break;
- char codeUnit = (char)(((compressedLSB & 0xFF) << 8) |
- (Util.readByteLE(filename, extendedDataPointer++) & 0xFF));
- if(debug) System.out.println(" Encountered compressed 16-bit character: 0x" +
- Util.toHexStringBE(codeUnit));
- //codeUnitList.add(codeUnit);
- unicodeFilename[unicodeFilenamePointer++] = codeUnit;
- ++codeUnitsRead;
- }
- else if(current == 0x2) { // 0b10
- //if(extendedDataPointer+1 >= filename.length) break;
- char codeUnit = (char)Util.readShortLE(filename, extendedDataPointer);
- extendedDataPointer += 2;
- if(debug) System.out.println(" Encountered 16-bit character: 0x" + Util.toHexStringBE(codeUnit));
- //codeUnitList.add(codeUnit);
- unicodeFilename[unicodeFilenamePointer++] = codeUnit;
- ++codeUnitsRead;
- }
- else if(current == 0x3) {
- //if(extendedDataPointer >= filename.length) break;
- byte indicator = Util.readByteLE(filename, extendedDataPointer++);
-
- /* Detta �r bullshit. Det �r INTE en indikator utan ett "skip"-kommando.
- * Ex. skip(0x02) => Spola f�rbi 4 characters dvs. ".txt" (n�stan alla test*+.rar)
- * skip(0x05) => Spola f�rbi 7 characters ex. "bok.txt" (ctest6.rar)
- * skip(0x01) => Spola f�rbi 3 characters ex. "Hej" (ctest16.rar)
- * skip(0x03) => Spola f�rbi 5 characters ex. "laban" (ctest16.rar)
- * Specialfall:
- * - Man kan som minst spola f�rbi 2 characters (skip(0x00)). Om str�ngen inleds med
- * en ASCII-character med Unicode-char direkt f�ljande s� kodas ASCII-charactern ner
- * som Unicode.
- * - P� samma s�tt kan man inte spola f�rbi 131 characters, utan �r tvungen att koda
- * skip(0x7F)... eller n�t. iaf skitsamma. orka.
- */
-
- if((indicator & 0xFF) > 0x7F)
- System.out.println(" Encountered unexpected skip value! 0x" + Util.toHexStringBE(indicator));
- if(debug) System.out.println(" Skipping " + (indicator+2) + " bytes.");
-
- System.arraycopy(legacyFilename, unicodeFilenamePointer, unicodeFilename, unicodeFilenamePointer, (indicator+2));
- unicodeFilenamePointer += (indicator+2);
- }
- }
- }
- if(unicodeFilenamePointer != legacyFilename.length)
- if(debug) System.out.println(" ERROR! Did not read enough characters. Read " + unicodeFilenamePointer + " characters while legacyFilename.length==" + legacyFilename.length + ".");
- else
- if(debug) System.out.println(" Read " + unicodeFilenamePointer + " characters.");
- return new String(unicodeFilename);
- }
-
- public byte[] getTrailingFilenameData() {
- for(int i = 0; i < filename.length; ++i) {
- if(filename[i] == 0)
- return Util.createCopy(filename, i, filename.length-i);
- }
- return new byte[0];
- }
-
- public static String hostOSToString(byte hostOS) {
- if(hostOS >= 0 && hostOS <= hostOSStrings.length)
- return hostOSStrings[hostOS];
- else
- return null;
- }
-
- /* // An attempt at porting the CRC-function from unrarlib to Java. Seems to work poorly.
- private static class MyCRC32 {
- private final int[] CRCTab = new int[256];
- private int currentCRC = 0xFFFFFFFF;
- public MyCRC32() {
- short I, J;
- int C;
- for(I=0;(I&0xFFFF)<256;I++) {
- for(C=I,J=0;J<8;J++)
- C=((C & 1) != 0)? (C>>1)^0xEDB88320 : (C>>1);
- CRCTab[I&0xFFFF]=C;
- }
- }
-
- public void update(byte[] data) {
- currentCRC = CalcCRC32(currentCRC, data);
- }
-
- public int getValue() {
- return currentCRC;
- }
-
- private int CalcCRC32(int StartCRC, byte[] Addr) {
- short I;
- for(I=0; I<Addr.length; I++)
- StartCRC = CRCTab[((byte)StartCRC ^ Addr[I])&0xFF] ^ (StartCRC >> 8);
- return(StartCRC);
- }
- }
- */
-
-
- protected void printFields(PrintStream ps, String prefix) {
- super.printFields(ps, prefix);
- ps.println(prefix + " PackSize: " + getPackSize() + " bytes");
- ps.println(prefix + " UnpSize: " + getUnpSize() + " bytes");
- ps.println(prefix + " HostOS: \"" + getHostOSAsString() + "\"");
- ps.println(prefix + " FileCRC: 0x" + Util.toHexStringBE(getFileCRC()));
- ps.println(prefix + " FileTime: " + getFileTimeAsDate() + " (0x" + Util.toHexStringBE(getFileTime()) + ")");
- ps.println(prefix + " UnpVer: \"" + getUnpackVersionAsString() + "\"");
- ps.println(prefix + " Method: 0x" + Util.toHexStringBE(getMethod()));
- ps.println(prefix + " NameSize: " + getNameSize() + " bytes");
- ps.println(prefix + " FileAttr: 0x" + Util.toHexStringBE(getFileAttr()));
- ps.println(prefix + " Structured file attributes:");
- getFileAttributesStructured().print(ps, prefix + " ");
- ps.println(prefix + " Filename: \"" + getFilenameAsString() + "\"");
- byte[] trailingFilenameData = getTrailingFilenameData();
- if(trailingFilenameData.length > 0)
- ps.println(prefix + " (Trailing filename data: 0x" + Util.byteArrayToHexString(trailingFilenameData) + ")");
- ps.println(prefix + " Trailing data: 0x" + Util.byteArrayToHexString(getTrailingData()));
- }
-
- public void print(PrintStream ps, String prefix) {
- ps.println(prefix + "NewFileHeader: ");
- printFields(ps, prefix);
- }
-}
diff --git a/src/org/catacombae/rarx/NewMainArchiveHeader.java b/src/org/catacombae/rarx/NewMainArchiveHeader.java
deleted file mode 100644
index caf09db..0000000
--- a/src/org/catacombae/rarx/NewMainArchiveHeader.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.io.PrintStream;
-
-public class NewMainArchiveHeader extends RARHeader {
- /*
- * struct NewMainArchiveHeader
- * size: 13 bytes
- *
- * BP Size Description
- * 0 2 HeadCRC
- * 2 1 HeadType
- * 3 2 Flags
- * 5 2 HeadSize
- * 7 2 Reserved
- * 9 4 Reserved1
- */
-
- private final byte[] reserved = new byte[2];
- private final byte[] reserved1 = new byte[4];
-
- public NewMainArchiveHeader(byte[] data, int offset) {
- super(data, offset);
- System.arraycopy(data, offset+7, reserved, 0, 2);
- System.arraycopy(data, offset+9, reserved1, 0, 4);
- validateData();
- }
-
- public int getSize() { return _getSize(); }
- private int _getSize() { return getHeadSize();/*13;*/ }
-
- protected void validateData() {
- super.validateData();
- if(getHeadType() != MAIN_HEAD)
- throw new InvalidDataException("Incorrect head type! (headType=" + getHeadType() + ")");
-// if(getHeadSize() != getSize())
-// throw new InvalidDataException("Wrong size! (size=" + getHeadSize() + ")");
- }
-
- public short getReserved() { return Util.readShortLE(reserved); }
- public int getReserved1() { return Util.readIntLE(reserved1); }
-
- public byte[] getHeaderData() {
- byte[] data = new byte[_getSize()];
- System.arraycopy(super.getHeaderData(), 0, data, 0, super.getSize());
- System.arraycopy(reserved, 0, data, 7, 2);
- System.arraycopy(reserved1, 0, data, 9, 4);
- return data;
- }
-// public short calculateHeadCRC() {
-// CRC32 crc = new CRC32();
-// //MyCRC32 crc = new MyCRC32();
-// // crc.update(headCRC);
-// crc.update(headType);
-// crc.update(flags);
-// crc.update(headSize);
-// crc.update(reserved);
-// crc.update(reserved1);
-// //crc.(trailingData);
-// return (short)(crc.getValue());
-// }
-
- protected void printFields(PrintStream ps, String prefix) {
- super.printFields(ps, prefix);
- ps.println(prefix + " Reserved: " + Util.toHexStringBE(getReserved()));
- ps.println(prefix + " Reserved1: " + Util.toHexStringBE(getReserved1()));
- }
-
-
- public void print(PrintStream ps, String prefix) {
- ps.println(prefix + "NewMainArchiveHeader: ");
- printFields(ps, prefix);
- }
-}
diff --git a/src/org/catacombae/rarx/ProtectedHeader.java b/src/org/catacombae/rarx/ProtectedHeader.java
deleted file mode 100644
index 0f7df6d..0000000
--- a/src/org/catacombae/rarx/ProtectedHeader.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.io.PrintStream;
-
-public class ProtectedHeader extends RARHeader {
- private final byte[] dataSize = new byte[4];
- private final byte[] unknownData;
- public ProtectedHeader(byte[] data, int offset) {
- super(data, offset);
- System.arraycopy(data, super.getSize(), dataSize, 0, 4);
- unknownData = new byte[getHeadSize()-(super.getSize()+4)];
- System.arraycopy(data, super.getSize()+4, unknownData, 0, unknownData.length);
- validateData();
- }
-
- public int getSize() {
- return _getSize();
- }
-
- private int _getSize() {
- return super.getSize()+dataSize.length+unknownData.length;
- }
-
- public void validateData() {
- super.validateData();
- if(getHeadType() != PROTECT_HEAD)
- throw new InvalidDataException("Incorrect head type! (headType=" + getHeadType() + ")");
- }
-
- public byte[] getHeaderData() {
- byte[] outData = new byte[_getSize()];
- byte[] superData = super.getHeaderData();
- System.arraycopy(superData, 0, outData, 0, superData.length);
- System.arraycopy(dataSize, 0, outData, superData.length, dataSize.length);
- System.arraycopy(unknownData, 0, outData, superData.length+dataSize.length, unknownData.length);
- return outData;
- }
-
- public long getDataSize() {
- return Util.readIntLE(dataSize, 0) & 0xFFFFFFFFL;
- }
-
- public void print(PrintStream ps, String prefix) {
- System.out.println("Protected header:");
- printFields(ps, prefix);
- }
-}
diff --git a/src/org/catacombae/rarx/RARFile.java b/src/org/catacombae/rarx/RARFile.java
deleted file mode 100644
index 3c63a22..0000000
--- a/src/org/catacombae/rarx/RARFile.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.util.Vector;
-import java.io.*;
-import java.util.zip.CRC32;
-
-public class RARFile {
- public static final int SIZEOF_MARKHEAD = 7;
- public static final int SIZEOF_OLDMHD = 7;
- public static final int SIZEOF_NEWMHD = 13;
- public static final int SIZEOF_OLDLHD = 21;
- public static final int SIZEOF_NEWLHD = 32;
- public static final int SIZEOF_SHORTBLOCKHEAD = 7;
- public static final int SIZEOF_LONGBLOCKHEAD = 11;
- public static final int SIZEOF_COMMHEAD = 13;
- public static final int SIZEOF_PROTECTHEAD = 26;
-
- private static BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
-
- public static void main(String[] args) throws IOException {
- File fileListFile = new File(args[0]);
- BufferedReader fileListIn = new BufferedReader(new InputStreamReader(new FileInputStream(fileListFile), "UTF-8"));
- String currentRar = fileListIn.readLine();
- while(currentRar != null) {
- if(true) {
- System.out.println("Processing file " + currentRar + "...");
- try {
- RARFileEntry[] entries = ListFilesInArchive.listFiles(new File(currentRar));
- for(RARFileEntry entry : entries) {
- NewFileHeader nfh = entry.getHeader(0);
- if(nfh instanceof CommentHeader)
- continue;
- //if(nfh.hasOutgoingData())
- System.out.print((nfh.hasIncomingData()?"<--":" ") + nfh.getFilenameAsString() + (nfh.hasOutgoingData()?"-->":""));
- if(nfh.getFileAttributesStructured().isDirectory())
- System.out.print(" (Dir)");
- else
- System.out.print(" (File)");
- System.out.println();
- }
- } catch(InvalidDataException ide) {
- System.out.println("Invalid RAR-file. Message: " + ide.getMessage());
- System.out.println("File: \"" + currentRar + "\"");
- }
- }
- else {
- RandomAccessFile raf = new RandomAccessFile(currentRar, "r");
- try {
- readMarkHeader(raf);
- NewMainArchiveHeader nmah = readNewMainArchiveHeader(raf);
- NewFileHeader nfh = readNewFileHeader(raf);
- } catch(InvalidDataException e) {
- System.out.println("Invalid RAR-file. Message: " + e.getMessage());
- System.out.println("File: \"" + currentRar + "\"");
- //System.exit(1);
- }
- }
- System.out.print("Press enter to continue...");
- stdin.readLine();
- System.out.println();
- currentRar = fileListIn.readLine();
- }
- }
- public static void main2(String[] args) throws IOException {
- RandomAccessFile raf = new RandomAccessFile(args[0], "r");
- try {
- readMarkHeader(raf);
- } catch(InvalidDataException e) {
- System.out.println("Invalid RAR-file. Message: " + e.getMessage());
- System.exit(1);
- }
-
- NewMainArchiveHeader nmah = readNewMainArchiveHeader(raf);
- nmah.print(System.out, "");
- NewFileHeader nfh = readNewFileHeader(raf);
- nfh.print(System.out, "");
- }
-
- public static Vector list(String path, boolean fullPath) throws IOException {
- RandomAccessFile raf = new RandomAccessFile(path, "r");
- raf.seek(7);
- NewMainArchiveHeader nmah = readNewMainArchiveHeader(raf);
- return null;
- }
-
- public static boolean isRAR(RandomAccessFile raf) throws IOException {
- long oldFilePointer = raf.getFilePointer();
- raf.seek(0);
- byte[] rarHeader = new byte[7];
- raf.read(rarHeader);
- /* Old archive => error */
- if(rarHeader[0]==0x52 && rarHeader[1]==0x45 &&
- rarHeader[2]==0x7e && rarHeader[3]==0x5e) {
- //debug_log("Attention: format as OLD detected! Can't handle archive!");
- }
- else {
- /* original RAR v2.0 */
- if((rarHeader[0]==0x52 && rarHeader[1]==0x61 && /* original */
- rarHeader[2]==0x72 && rarHeader[3]==0x21 && /* RAR header*/
- rarHeader[4]==0x1a && rarHeader[5]==0x07 &&
- rarHeader[6]==0x00) ||
- /* "UniquE!" - header */
- (rarHeader[0]=='U' && rarHeader[1]=='n' && /* "UniquE!" */
- rarHeader[2]=='i' && rarHeader[3]=='q' && /* header */
- rarHeader[4]=='u' && rarHeader[5]=='E' &&
- rarHeader[6]=='!')) {
- if(readNewMainArchiveHeader(raf) != null)
- return true;
- } else {
- // Skriv ut n�t felmedd...
- }
- }
- return false;
- }
-
- public static MarkHeader readMarkHeader(RandomAccessFile raf) throws IOException {
- byte[] header = new byte[7];
- raf.read(header);
- MarkHeader nfh = new MarkHeader(header, 0);
- return nfh;
- }
- public static NewMainArchiveHeader readNewMainArchiveHeader(RandomAccessFile raf) throws IOException {
- byte[] mainHeader = new byte[13];
- raf.read(mainHeader);
- NewMainArchiveHeader nmah = new NewMainArchiveHeader(mainHeader, 0);
- return nmah;
- }
-
- public static NewFileHeader readNewFileHeader(RandomAccessFile raf) throws IOException {
- byte[] header = new byte[32];
- raf.read(header);
- int headerSize = Util.readShortLE(header, 5);
- byte[] fullHeader = new byte[headerSize];
- System.arraycopy(header, 0, fullHeader, 0, header.length);
- raf.read(fullHeader, header.length, fullHeader.length-header.length);
- NewFileHeader nfh = new NewFileHeader(fullHeader, 0);
- byte[] reconstruction = nfh.getHeaderData();
- if(!Util.arraysEqual(fullHeader, reconstruction))
- System.out.println("ERROR: Data after reconstruction has changed!");
- return nfh;
- }
-
- public static RARHeader readHeader(RandomAccessFile raf) throws IOException {
- byte[] header = new byte[7];
- if(raf.read(header) == -1)
- return null;
- int headerSize = Util.readShortLE(header, 5);
- byte headerType = Util.readByteLE(header, 2);
- try {
- byte[] fullHeader = new byte[headerSize];
- System.arraycopy(header, 0, fullHeader, 0, header.length);
- raf.read(fullHeader, header.length, fullHeader.length-header.length);
- //System.out.println("Reading... headerSize=" + headerSize + " headerType=" + headerType);
- if(headerType == RARHeader.FILE_HEAD) {
- NewFileHeader nfh = new NewFileHeader(fullHeader, 0);
- raf.seek(raf.getFilePointer()+nfh.getPackSize());
- return nfh;
- }
- else if(headerType == RARHeader.MAIN_HEAD)
- return new NewMainArchiveHeader(fullHeader, 0);
- else if(headerType == RARHeader.COMMENT_HEAD) {
- CommentHeader ch = new CommentHeader(fullHeader, 0);
- raf.seek(raf.getFilePointer()+ch.getPackSize());
- return ch;
- }
- else if(headerType == RARHeader.PROTECT_HEAD) {
- ProtectedHeader ph = new ProtectedHeader(fullHeader, 0);
- raf.seek(raf.getFilePointer()+ph.getDataSize());
- return ph;
- }
- else if(headerType == RARHeader.EOF_HEAD)
- return null;
- else {
- System.out.println("UNRECOGNIZED HEADER TYPE: 0x" + Util.toHexStringBE(headerType) + " for header at 0x" + Util.toHexStringBE(raf.getFilePointer()-headerSize));
- UnknownHeader uh = new UnknownHeader(fullHeader, 0);
- uh.print(System.out, "");
- return uh;
- }
- } catch(ArrayIndexOutOfBoundsException aioobe) {
- aioobe.printStackTrace();
- System.err.println("headerSize=" + headerSize);
- System.err.println("headerType=" + headerType);
- System.err.println("filePointer: " + raf.getFilePointer());
- return null;
- }
- }
-
- public static long findEntry(String entryName, RandomAccessFile rarFile) throws IOException {
- readMarkHeader(rarFile);
- RARHeader currentHeader = readHeader(rarFile);
- while(currentHeader != null) {
- if(currentHeader instanceof NewFileHeader &&
- !(currentHeader instanceof CommentHeader)) {
- NewFileHeader nfh = (NewFileHeader)currentHeader;
- if(nfh.getFilenameAsString().equals(entryName)) {
- return rarFile.getFilePointer() - (nfh.getHeadSize()+nfh.getPackSize());
- }
- }
- currentHeader = readHeader(rarFile);
- }
- return -1;
- }
-
- // Utility methods
-
-// public static int readIntLE(byte[] data) {
-// return readIntLE(data, 0);
-// }
-// public static int readIntLE(byte[] data, int offset) {
-// return ((data[offset+3] & 0xFF) << 24 |
-// (data[offset+2] & 0xFF) << 16 |
-// (data[offset+1] & 0xFF) << 8 |
-// (data[offset+0] & 0xFF) << 0);
-// }
-// public static short readShortLE(byte[] data) {
-// return readShortLE(data, 0);
-// }
-// public static short readShortLE(byte[] data, int offset) {
-// return (short) ((data[offset+1] & 0xFF) << 8 |
-// (data[offset+0] & 0xFF) << 0);
-// }
-// public static byte readByteLE(byte[] data) {
-// return readByteLE(data, 0);
-// }
-// public static byte readByteLE(byte[] data, int offset) {
-// return data[offset];
-// }
-}
diff --git a/src/org/catacombae/rarx/RARFile2.java b/src/org/catacombae/rarx/RARFile2.java
deleted file mode 100644
index df7f706..0000000
--- a/src/org/catacombae/rarx/RARFile2.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.io.IOException;
-
-public class RARFile2 {
- public static void main(String[] args) throws IOException {
- RARFile.main2(args);
- }
-}
diff --git a/src/org/catacombae/rarx/RARFileEntry.java b/src/org/catacombae/rarx/RARFileEntry.java
deleted file mode 100644
index ff8410d..0000000
--- a/src/org/catacombae/rarx/RARFileEntry.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.util.ArrayList;
-import java.io.File;
-
-public class RARFileEntry {
- public static class RARFileEntryPart {
- public File f;
- public long offset;
- public NewFileHeader header;
-
- public RARFileEntryPart(File f, long offset, NewFileHeader header) {
- this.f = f;
- this.offset = offset;
- this.header = header;
- }
- }
-
- private ArrayList<RARFileEntryPart> parts = new ArrayList<RARFileEntryPart>();
-
- public RARFileEntry(File f, long offset, NewFileHeader header) {
- RARFileEntryPart firstPart = new RARFileEntryPart(f, offset, header);
- parts.add(firstPart);
- }
-
- public void addPart(File f, long offset, NewFileHeader header) {
- parts.add(new RARFileEntryPart(f, offset, header));
- }
-
- public int getPartCount() { return parts.size(); }
- public long getPackedSize() {
- long size = 0;
- for(RARFileEntryPart current : parts)
- size += current.header.getPackSize();
- return size;
- }
-
- public boolean hasIncomingData() {
- return parts.get(0).header.hasIncomingData();
- }
- public boolean hasOutgoingData() {
- return parts.get(parts.size()-1).header.hasOutgoingData();
- }
-
- public boolean isComplete() {
- return (!parts.get(0).header.hasIncomingData() && !parts.get(parts.size()-1).header.hasOutgoingData());
- }
-
- public int getFinalFileCRC() {
- return parts.get(parts.size()-1).header.getFileCRC();
- }
-
- public File getFile(int partNumber) { return parts.get(partNumber).f; }
- public long getOffset(int partNumber) { return parts.get(partNumber).offset; }
- public NewFileHeader getHeader(int partNumber) { return parts.get(partNumber).header; }
-}
diff --git a/src/org/catacombae/rarx/RARFileEntryStream.java b/src/org/catacombae/rarx/RARFileEntryStream.java
deleted file mode 100644
index c632900..0000000
--- a/src/org/catacombae/rarx/RARFileEntryStream.java
+++ /dev/null
@@ -1,550 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import org.catacombae.io.*;
-import java.io.*;
-import java.util.LinkedList;
-import java.util.regex.Pattern;
-
-public class RARFileEntryStream implements RandomAccessStream {
- public static class InvalidRARFilenameException extends RuntimeException {
- private static final long serialVersionUID = 0x2F49329E49173487L;
-
- public InvalidRARFilenameException(String message) {
- super(message);
- }
- }
-
- public static class RAREntrySegment {
- public File file;
- public RandomAccessFile raf;
- public long headerPos;
- public long headerLength;
- public long dataPos;
- public long dataLength;
- public RAREntrySegment nextSegment = null;
-
- public RAREntrySegment(File file, RandomAccessFile raf, long headerPos, long headerLength, long dataPos, long dataLength/*, RAREntrySegment nextSegment*/) {
- this.file = file;
- this.raf = raf;
- this.headerPos = headerPos;
- this.headerLength = headerLength;
- this.dataPos = dataPos;
- this.dataLength = dataLength;
- //this.nextSegment = nextSegment;
- }
- }
-
- public class Interval {
- public RAREntrySegment segment;
- public long startOffset;
- public long endOffset;
-
- public Interval(RAREntrySegment segment, long startOffset, long endOffset) {
- this.segment = segment;
- this.startOffset = startOffset;
- this.endOffset = endOffset;
- }
- }
-
- public class IntervalStructure {
- private LinkedList<Interval> intervals = new LinkedList<Interval>();
-
- public void addSegment(RAREntrySegment res, long startOffset, long endOffset) {
- Interval newInterval = new Interval(res, startOffset, endOffset);
- if(intervals.size() > 0) {
- Interval previous = intervals.getLast();
- previous.segment.nextSegment = newInterval.segment;
- }
- intervals.addLast(newInterval);
- }
-
- public RAREntrySegment getSegment(long offset) {
- for(Interval i : intervals)
- if(offset >= i.startOffset && offset < i.endOffset)
- return i.segment;
- return null;
- }
-
- public Interval getInterval(long offset) {
- for(Interval i : intervals)
- if(offset >= i.startOffset && offset < i.endOffset)
- return i;
- return null;
- }
-
- public RAREntrySegment[] getAllSegmentsUnordered() {
- RAREntrySegment[] result = new RAREntrySegment[intervals.size()];
- int j = 0;
- for(Interval i : intervals)
- result[j++] = i.segment;
- return result;
- }
- }
-
- public static boolean debug = false;
- private IntervalStructure intervalStructure;
- private RAREntrySegment currentSegment;
- private boolean closed = false;
- private long seekPointer;
- private long globalPointer = 0;
- private long segmentPointer = 0;
- private final long length;
-
- public RARFileEntryStream(RARFileEntry entry) throws FileNotFoundException, IOException {
- this(entry.getFile(0), entry.getOffset(0));
- }
-
- public RARFileEntryStream(File startFile, long pos) throws FileNotFoundException, IOException {
- //this.startFile = startFile;
- //this.pos = pos;
-
- LinkedList<RAREntrySegment> entrySegments = getSegments(startFile, pos, new LinkedList<RAREntrySegment>(), false);
-// for(RAREntrySegment res : entrySegments)
-// res.raf.seek(0);
- if(entrySegments == null || entrySegments.size() < 1)
- throw new FileNotFoundException();
- this.currentSegment = entrySegments.getFirst();
-
- long currentPos = 0;
- this.intervalStructure = new IntervalStructure();
- for(RAREntrySegment res : entrySegments) {
- if(debug) System.out.println("Adding \"" + res.file + "\" at " + currentPos);
- intervalStructure.addSegment(res, currentPos, currentPos+res.dataLength);
- currentPos += res.dataLength;
- }
- length = currentPos;
- if(debug) System.out.println("Length of entry: " + length + " bytes");
-
- seekPointer = -2;
- updateSeekPosition();
- }
-
- /** @see java.io.RandomAccessFile */
- public synchronized void close() throws IOException {
- if(debug) System.out.println("RARFileEntryStream.close()");
- if(closed) throw new IOException("Stream closed.");
-
- closed = true;
- for(RAREntrySegment res : intervalStructure.getAllSegmentsUnordered())
- res.raf.close();
- }
-
- /** @see java.io.RandomAccessFile */
- public synchronized long getFilePointer() throws IOException {
- return ((seekPointer == -1)?globalPointer:seekPointer);
- }
-
- /** @see java.io.RandomAccessFile */
- public synchronized long length() throws IOException {
- return length;
- }
-
- /** @see java.io.RandomAccessFile */
- public synchronized int read() throws IOException {
- if(closed) throw new IOException("Stream closed.");
- byte[] b = new byte[1];
- read(b, 0, 1);
- return b[0] & 0xFF;
- }
-
- /** @see java.io.RandomAccessFile */
- public synchronized int read(byte[] b) throws IOException {
- if(closed) throw new IOException("Stream closed.");
- return read(b, 0, b.length);
- }
-
- /** @see java.io.RandomAccessFile */
- public synchronized int read(byte[] b, int off, int len) throws IOException {
-// boolean debug = true;
- if(debug) System.out.print("RARFileEntryStream.read(b, " + off + ", " + len + ") = ");
-// System.out.println();
-// System.out.println("(1)currentSegment.raf.getFilePointer()=" + currentSegment.raf.getFilePointer());
-// System.out.println("(1)=seekPointer=" + seekPointer);
- if(closed) throw new IOException("Stream closed.");
- try {
- updateSeekPosition();
- } catch(IOException ioe) {
- if(debug) System.out.println("-1 (Couldn't update seek position)");
- return -1;
- }
-
- long bytesRemainingInSegment = currentSegment.dataLength - segmentPointer;
- while(bytesRemainingInSegment == 0) {
- if(nextSegment())
- bytesRemainingInSegment = currentSegment.dataLength - segmentPointer;
- else {
- if(debug) System.out.println("-1 (Nothing to read)");
- return -1; // Nothing to read!
- }
- }
- int bytesRead = 0;
- mainLoop:
- while(bytesRead < len) {
- int remainingBytes = len-bytesRead;
- int bytesToRead = (remainingBytes < bytesRemainingInSegment)?remainingBytes:(int)bytesRemainingInSegment;
-
-// System.out.println("(2)currentSegment.raf.getFilePointer()=" + currentSegment.raf.getFilePointer());
- int currentBytesRead = currentSegment.raf.read(b, off+bytesRead, bytesToRead);
- if(currentBytesRead == -1)
- throw new IOException("Reached end of file unexpectedly for file \"" + currentSegment.file + "\"! (segmentPointer=" + segmentPointer + " globalPointer=" + globalPointer + " bytesRemainingInSegment=" + bytesRemainingInSegment + " bytesRead=" + bytesRead + " bytesToRead=" + bytesToRead + " currentSegment.raf.getFilePointer()=" + currentSegment.raf.getFilePointer() + " currentSegment.dataLength=" + currentSegment.dataLength + ")");
-
- bytesRead += currentBytesRead;
- segmentPointer += currentBytesRead;
- globalPointer += currentBytesRead;
- //seekPointer += currentBytesRead;
-
- bytesRemainingInSegment = currentSegment.dataLength - segmentPointer;
- while(bytesRemainingInSegment == 0) {
- if(nextSegment())
- bytesRemainingInSegment = currentSegment.dataLength - segmentPointer;
- else
- break mainLoop; // No more bytes to read;
- }
- }
- if(debug) System.out.println(bytesRead);
- return bytesRead;
- }
-
- /** @see java.io.RandomAccessFile */
- public synchronized void seek(long pos) throws IOException {
- if(debug) System.out.println("RARFileEntryStream.seek(" + pos + ")");
- if(closed) throw new IOException("Stream closed.");
- if(pos < 0) throw new IOException("Invalid position.");
- seekPointer = pos;
- }
-
- private synchronized void updateSeekPosition() throws IOException {
- if(debug) System.out.println("updateSeekPosition()");
-// System.out.println("seekPointer=" + seekPointer);
-// System.out.println("globalPointer=" + globalPointer);
-// System.out.println("segmentPointer=" + segmentPointer);
- if(seekPointer == globalPointer)
- seekPointer = -1;
- else if(seekPointer != -1) {
- //if(seekPointer > length) seek(length-1);
- if(seekPointer == -2)
- seekPointer = 0;
-
- long posDiff = seekPointer-globalPointer;
- long newSegmentPointer = segmentPointer + posDiff;
- if(newSegmentPointer >= 0 &&
- newSegmentPointer < currentSegment.dataLength) {
- if(debug) System.out.println(" Pointer is within segment.");
- globalPointer += posDiff;
- segmentPointer += posDiff;
- if(debug) System.out.println(" Seeking to " + (currentSegment.dataPos + segmentPointer) +".");
- currentSegment.raf.seek(currentSegment.dataPos + segmentPointer);
- if(debug) System.out.println(" Done.");
- }
- else {
- if(debug) System.out.println(" Pointer is OUTSIDE segment. We need to get a new one.");
- Interval newInterval = intervalStructure.getInterval(seekPointer);
- if(newInterval == null)
- throw new IOException("No more data to read.");
- RAREntrySegment newSegment = newInterval.segment;
- newSegmentPointer = (seekPointer-newInterval.startOffset);
- if(debug) System.out.println(" Seeking to " + (currentSegment.dataPos + segmentPointer) +".");
- newSegment.raf.seek(newSegment.dataPos + newSegmentPointer);
- if(debug) System.out.println(" Done.");
-
- // If we got here, all is well.
- globalPointer = seekPointer;
- segmentPointer = newSegmentPointer;
- currentSegment = newSegment;
- }
- seekPointer = -1;
- }
- }
-
- public synchronized boolean isClosed() {
- return closed;
- }
-
- public synchronized boolean reopen() {
- if(debug) System.out.println("RARFileEntryStream.reopen()");
- if(closed) {
- try {
- for(RAREntrySegment res : intervalStructure.getAllSegmentsUnordered())
- res.raf = new RandomAccessFile(res.file, "r");
- closed = false;
- seekPointer = -2;
- updateSeekPosition();
- //seek(0);
- return true;
- } catch(Exception e) {}
- }
- return false;
- }
-
- /**
- * Changes forward to the next segment and sets the pointers.
- */
- private boolean nextSegment() throws IOException {
- if(debug) System.out.println("RARFileEntryStream.nextSegment()");
- RAREntrySegment nextSegment = currentSegment.nextSegment;
- if(nextSegment != null) {
- if(debug) System.out.println(" nextSegment != null");
- if(debug) System.out.println(" currentSegment: " + currentSegment);
- if(debug) System.out.println(" file: " + currentSegment.file);
- if(debug) System.out.println(" headerPos: " + currentSegment.headerPos);
- if(debug) System.out.println(" headerLength: " + currentSegment.headerLength);
- if(debug) System.out.println(" dataPos: " + currentSegment.dataPos);
- if(debug) System.out.println(" dataLength: " + currentSegment.dataLength);
- if(debug) System.out.println(" nextSegment: " + nextSegment);
- if(debug) System.out.println(" file: " + nextSegment.file);
- if(debug) System.out.println(" headerPos: " + nextSegment.headerPos);
- if(debug) System.out.println(" headerLength: " + nextSegment.headerLength);
- if(debug) System.out.println(" dataPos: " + nextSegment.dataPos);
- if(debug) System.out.println(" dataLength: " + nextSegment.dataLength);
- globalPointer += currentSegment.dataLength - segmentPointer;
- segmentPointer = 0;
- nextSegment.raf.seek(nextSegment.dataPos);
- currentSegment = nextSegment;
- return true;
- }
- else {
- if(debug) System.out.println(" nextSegment == null");
- return false;
- }
- }
-
- private static LinkedList<RAREntrySegment> getSegments(File file, long position, LinkedList<RAREntrySegment> list, boolean needsIncoming) throws IOException, FileNotFoundException {
- if(debug) System.out.println("Getting new entry segment: " + file);
- RandomAccessFile raf = new RandomAccessFile(file, "r");
- raf.seek(position);
- RARHeader rh = RARFile.readHeader(raf);
- if(rh instanceof NewFileHeader) {
- NewFileHeader nfh = (NewFileHeader)rh;
- if(//nfh.getMethod() == RARHeader.METHOD_UNCOMPRESSED &&
- (needsIncoming?nfh.hasIncomingData():!nfh.hasIncomingData()) &&
- !(nfh instanceof CommentHeader)) {
- RAREntrySegment res = new RAREntrySegment(file, raf, position, nfh.getSize(), position+nfh.getSize(), nfh.getPackSize());
- list.addLast(res);
- if(nfh.hasOutgoingData()) {
- File nextFile = getNextFile(file);
- if(nextFile == null)
- throw new FileNotFoundException();
- long posInNextFile = getMatchingPosInFile(nextFile, nfh);
- if(posInNextFile == -1)
- throw new FileNotFoundException();
- getSegments(nextFile, posInNextFile, list, true);
- }
- }
- }
- return list;
- }
-
- protected static File getNextFile(File rarFile) {
- String filename = rarFile.getName();
- String newFilename;
- if(Pattern.matches(".+\\.[P|p]art\\d+\\.rar", filename)) {
- String numberString = "";
- long partNumber = 0; // I'm not serious... (:
- int charstep = 0;
- while(true) {
- String currentNumber = filename.substring(filename.length()-5-charstep, filename.length()-4-charstep);
- try {
- partNumber += Integer.parseInt(currentNumber)*Util.pow(10, charstep);
- } catch(NumberFormatException nfe) {
- break;
- }
- ++charstep;
- }
- int numberLength = charstep;
- String newPartNumberString = "" + (partNumber + 1);
-
- // Add leading zeroes
- while(newPartNumberString.length() < numberLength)
- newPartNumberString = "0" + newPartNumberString;
-
- newFilename = filename.substring(0, filename.length()-4-numberLength) + newPartNumberString + ".rar";
- }
- else if(Pattern.matches(".+\\.r((ar)|(\\d\\d)){1}", filename)) {
- String lastTwo = filename.substring(filename.length()-2, filename.length());
- String newLastTwo = "";
- if(lastTwo.equals("ar"))
- newLastTwo = "00";
- else {
- try {
- int archiveNumber = Integer.parseInt(lastTwo);
- newLastTwo = "" + (archiveNumber+1);
- if(newLastTwo.length() < 2)
- newLastTwo = "0" + newLastTwo;
- } catch(NumberFormatException nfe) {
- throw new RuntimeException(nfe);
- }
- }
- if(newLastTwo.length() != 2)
- throw new InvalidRARFilenameException("Incremented filename invalid.");
-
- newFilename = filename.substring(0, filename.length()-2) + newLastTwo;
- }
- else if(Pattern.matches(".+\\.\\d\\d\\d", filename)) {
- String lastThree = filename.substring(filename.length()-3, filename.length());
- String newLastThree = "";
- try {
- int archiveNumber = Integer.parseInt(lastThree);
- newLastThree = "" + (archiveNumber+1);
- while(newLastThree.length() < 3)
- newLastThree = "0" + newLastThree;
- } catch(NumberFormatException nfe) {
- throw new RuntimeException(nfe);
- }
- if(newLastThree.length() != 3)
- throw new InvalidRARFilenameException("Incremented filename invalid.");
-
- newFilename = filename.substring(0, filename.length()-3) + newLastThree;
- }
- else
- throw new InvalidRARFilenameException("Filename in argument invalid for a RAR-file.");
-
- File newFile = new File(rarFile.getParent(), newFilename);
- if(newFile.exists())
- return newFile;
- else {
- if(debug) System.out.println("Couldn't find \"" + newFile + "\"");
- return null;
- }
- }
-
- private static long getMatchingPosInFile(File f, NewFileHeader currentHeader) {
- try {
- RandomAccessFile raf = new RandomAccessFile(f, "r");
- RARFile.readMarkHeader(raf);
- RARHeader rh = RARFile.readHeader(raf);
- while(rh != null) {
- if(rh instanceof NewFileHeader) {
- NewFileHeader nextHeader = (NewFileHeader)rh;
- if(nextHeader.getFilenameAsString().equals(currentHeader.getFilenameAsString()) &&
- nextHeader.getUnpSize() == currentHeader.getUnpSize()) {
- long pos = raf.getFilePointer()-nextHeader.getPackSize()-nextHeader.getHeadSize();
- raf.close();
- return pos;
- }
- }
- rh = RARFile.readHeader(raf);
- }
- raf.close();
- } catch(IOException ioe) {
- ioe.printStackTrace();
- }
- return -1;
- }
-
- /** Testcode */
- public static void main(String[] args) throws IOException {
- if(args.length != 3)
- System.out.println("RARFileEntryStream self test needs exactly 3 arguments...");
- String rarFilename = args[0];
- String entryName = args[1];
- String referenceFilename = args[2];
-
- System.out.println("Initiating self test of RARFileEntryStream...");
- System.out.println(" RAR file: " + rarFilename);
- System.out.println(" Entry name: " + entryName);
- System.out.println(" Reference file: " + referenceFilename);
-
- File rarFile = new File(rarFilename);
- File referenceFile = new File(referenceFilename);
-
- long position = RARFile.findEntry(entryName, new RandomAccessFile(rarFile, "r"));
- RARFileEntryStream stream = new RARFileEntryStream(rarFile, position);
- RandomAccessFile ref = new RandomAccessFile(referenceFile, "r");
- byte[] buffer1 = new byte[4096];
- byte[] buffer2 = new byte[4096];
- int bytesRead1;
- int bytesRead2;
- long totalBytesRead1;
- long totalBytesRead2;
-
- System.out.println("1. Deterministic tests...");
- if(stream.length() != ref.length())
- System.out.println("Lengths not equal! stream: " + stream.length() + " reference file: " + ref.length());
-
- // Testing reading from the beginning
- ref.seek(0);
- stream.seek(0);
- if(ref.getFilePointer() != stream.getFilePointer()) throw new RuntimeException("File pointers not equal! ref: " + ref.getFilePointer() + " stream: " + stream.getFilePointer());
- bytesRead1 = ref.read(buffer1);
- bytesRead2 = stream.read(buffer2);
- if(ref.getFilePointer() != stream.getFilePointer()) throw new RuntimeException("File pointers not equal! ref: " + ref.getFilePointer() + " stream: " + stream.getFilePointer());
- if(bytesRead1 != bytesRead2) throw new RuntimeException("Did not read equal amount of bytes. (bytesRead1="+bytesRead1+" bytesRead2="+bytesRead2+")");
- if(!Util.arraysEqual(buffer1, buffer2)) throw new RuntimeException("Arrays not equal!");
-
- // Going to the middle of the file
- ref.seek(ref.length()/2);
- stream.seek(stream.length()/2);
- if(ref.getFilePointer() != stream.getFilePointer()) throw new RuntimeException("File pointers not equal! ref: " + ref.getFilePointer() + " stream: " + stream.getFilePointer());
- bytesRead1 = ref.read(buffer1);
- bytesRead2 = stream.read(buffer2);
- if(ref.getFilePointer() != stream.getFilePointer()) throw new RuntimeException("File pointers not equal! ref: " + ref.getFilePointer() + " stream: " + stream.getFilePointer());
- if(bytesRead1 != bytesRead2) throw new RuntimeException("Did not read equal amount of bytes. (bytesRead1="+bytesRead1+" bytesRead2="+bytesRead2+")");
- if(!Util.arraysEqual(buffer1, buffer2)) throw new RuntimeException("Arrays not equal!");
-
- // Going to the end of the file
- ref.seek(ref.length());
- stream.seek(stream.length());
- if(ref.getFilePointer() != stream.getFilePointer()) throw new RuntimeException("File pointers not equal! ref: " + ref.getFilePointer() + " stream: " + stream.getFilePointer());
- bytesRead1 = ref.read(buffer1);
- bytesRead2 = stream.read(buffer2);
- if(ref.getFilePointer() != stream.getFilePointer()) throw new RuntimeException("File pointers not equal! ref: " + ref.getFilePointer() + " stream: " + stream.getFilePointer());
- if(bytesRead1 != bytesRead2) throw new RuntimeException("Did not read equal amount of bytes. (bytesRead1="+bytesRead1+" bytesRead2="+bytesRead2+")");
- if(!Util.arraysEqual(buffer1, buffer2)) throw new RuntimeException("Arrays not equal!");
-
- // Going beyond the end of the file
- ref.seek(ref.length()*2);
- stream.seek(stream.length()*2);
- if(ref.getFilePointer() != stream.getFilePointer()) throw new RuntimeException("File pointers not equal! ref: " + ref.getFilePointer() + " stream: " + stream.getFilePointer());
- bytesRead1 = ref.read(buffer1);
- bytesRead2 = stream.read(buffer2);
- if(ref.getFilePointer() != stream.getFilePointer()) throw new RuntimeException("File pointers not equal! ref: " + ref.getFilePointer() + " stream: " + stream.getFilePointer());
- if(bytesRead1 != bytesRead2) throw new RuntimeException("Did not read equal amount of bytes. (bytesRead1="+bytesRead1+" bytesRead2="+bytesRead2+")");
- if(!Util.arraysEqual(buffer1, buffer2)) throw new RuntimeException("Arrays not equal!");
-
- // Comparing files byte for byte
- System.out.println("Comparing file data...");
- ref.seek(0);
- stream.seek(0);
- if(ref.getFilePointer() != stream.getFilePointer()) throw new RuntimeException("File pointers not equal! ref: " + ref.getFilePointer() + " stream: " + stream.getFilePointer());
- totalBytesRead1 = 0;
- totalBytesRead2 = 0;
- while(totalBytesRead1 < ref.length() && totalBytesRead2 < stream.length()) {
- System.out.print("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
- System.out.print(" " + totalBytesRead1 + " bytes processed");
- long bytesRemaining1 = ref.length()-totalBytesRead1;
- long bytesRemaining2 = ref.length()-totalBytesRead2;
- bytesRead1 = ref.read(buffer1, 0, (bytesRemaining1 < buffer1.length?(int)bytesRemaining1:buffer1.length));
- bytesRead2 = stream.read(buffer2, 0, (bytesRemaining2 < buffer2.length?(int)bytesRemaining2:buffer2.length));
- if(bytesRead1 != bytesRead2) throw new RuntimeException("Have not read equal amount of bytes. (bytesRead1="+bytesRead1+" bytesRead2="+bytesRead2+")");
- if(bytesRead1 == -1)
- break;
- totalBytesRead1 += bytesRead1;
- totalBytesRead2 += bytesRead2;
- if(ref.getFilePointer() != stream.getFilePointer()) throw new RuntimeException("File pointers not equal! ref: " + ref.getFilePointer() + " stream: " + stream.getFilePointer());
- if(totalBytesRead1 != totalBytesRead2) throw new RuntimeException("Have not read equal amount of bytes. (totalBytesRead1="+totalBytesRead1+" totalBytesRead2="+totalBytesRead2+")");
- if(!Util.arraysEqual(buffer1, buffer2)) throw new RuntimeException("Arrays not equal!");
- }
- System.out.print("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
- System.out.print(" " + totalBytesRead1 + " bytes processed");
- }
-}
diff --git a/src/org/catacombae/rarx/RARHeader.java b/src/org/catacombae/rarx/RARHeader.java
deleted file mode 100644
index c631f5f..0000000
--- a/src/org/catacombae/rarx/RARHeader.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.io.PrintStream;
-import java.util.zip.CRC32;
-
-public abstract class RARHeader {
- /*
- * Common fields for all RAR headers
- * size: 7 bytes
- *
- * BP Size Description
- * 0 2 HeadCRC
- * 2 1 HeadType
- * 3 2 Flags
- * 5 2 HeadSize
- */
- // Possible values for the fields headType in various classes
- //public static final int ALL_HEAD = 0;
- public static final int MARK_HEAD = 0x72; // 0x69 for UniquE! ones..? However, this field isn't really needed.
- public static final int MAIN_HEAD = 0x73;
- public static final int FILE_HEAD = 0x74;
- public static final int COMM_HEAD = 0x75;
- public static final int AV_HEAD = 0x76;
- public static final int SUB_HEAD = 0x77;
- public static final int PROTECT_HEAD = 0x78;
- public static final int COMMENT_HEAD = 0x7a;
- public static final int EOF_HEAD = 0x7b;
-
- /* The versioning seems very simple. version 2.0 is represented
- by the value 20 (0x14), 2.6 by the value 26 (0x1a) etc. */
- public static final int UNPACK_VERSION_2_0 = 0x14;
- public static final int UNPACK_VERSION_2_6 = 0x1a; // efterlyst-bfc.rar
- public static final int UNPACK_VERSION_2_9 = 0x1d;
-
- public static final int METHOD_UNCOMPRESSED = 0x30; // Observerad i 2.0, 2.9
- public static final int METHOD_COMPRESSION_1 = 0x35; // Observerad i 2.0, 2.9
- public static final int METHOD_COMPRESSION_2 = 0x33; // Observerad i 2.0 (flera g�nger, men ovanligt), 2.9
-
- /* Hypotes: de tv� minst signifikanta bitarna i Flags indikerar om en fil
- forts�tter p� nytt medium. Om bit 0 �r satt �r den aktuella filen en
- forts�ttning p� en tidigare fil. Om bit 1 �r satt forts�tter den
- aktuella filen p� ytterligare nya media.
- Hypotes bekr�ftad. */
-
-
- private final byte[] headCRC = new byte[2];
- private final byte[] headType = new byte[1];
- private final byte[] flags = new byte[2];
- private final byte[] headSize = new byte[2];
- private final CRC32 crc = new CRC32();
-
- public RARHeader(byte[] data, int offset) {
- System.arraycopy(data, offset+0, headCRC, 0, 2);
- System.arraycopy(data, offset+2, headType, 0, 1);
- System.arraycopy(data, offset+3, flags, 0, 2);
- System.arraycopy(data, offset+5, headSize, 0, 2);
- }
-
- public int getSize() { return _getSize(); }
- private int _getSize() { return 7; }
-
- protected void validateData() {
- if(calculateHeadCRC() != getHeadCRC())
- throw new InvalidDataException("Incorrect header CRC!");
- }
-
- public short getHeadCRC() { return Util.readShortLE(headCRC); }
- public byte getHeadType() { return Util.readByteLE(headType); }
- public short getFlags() { return Util.readShortLE(flags); }
- public short getHeadSize() { return Util.readShortLE(headSize); }
-
- public boolean getFlag(int bitNumber) {
- return Util.getBit(getFlags(), bitNumber);//((getFlags() >> byteNumber) & 0x1) == 0x1;
- }
-
-
- public byte[] getHeaderData() {
- byte[] data = new byte[_getSize()];
- System.arraycopy(headCRC, 0, data, 0, headCRC.length);
- System.arraycopy(headType, 0, data, 2, headType.length);
- System.arraycopy(flags, 0, data, 3, flags.length);
- System.arraycopy(headSize, 0, data, 5, headSize.length);
- return data;
- }
-
- public short calculateHeadCRC() {
- crc.reset();
- crc.update(getHeaderData(), 2, getSize()-2);
- return (short)(crc.getValue());
- }
- protected void printFields(PrintStream ps, String prefix) {
- ps.println(prefix + " HeadCRC: " + Util.toHexStringBE(getHeadCRC()));
- if(calculateHeadCRC() != getHeadCRC())
- ps.println(prefix + " CHECKSUMS NOT MATCHING! (0x" +
- Util.toHexStringBE(getHeadCRC()) + " != 0x" +
- Util.toHexStringBE(calculateHeadCRC()) + "))");
- ps.println(prefix + " HeadType: " + Util.toHexStringBE(getHeadType()));
- ps.println(prefix + " Flags: " + Util.toHexStringBE(getFlags()));
- ps.println(prefix + " HeadSize: " + getHeadSize() + " bytes");
- }
-}
diff --git a/src/org/catacombae/rarx/README.txt b/src/org/catacombae/rarx/README.txt
deleted file mode 100644
index 5e70dfd..0000000
--- a/src/org/catacombae/rarx/README.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-Acknowledgements
-----------------
-
-This code has been written with the UniquE RAR File Library v0.4.0 as a reference.
-Thus the author of this library should have a lot of credit for enabling me to write this code.
-I have not attributed him in the source files, as they have been written by myself in Java after
-studying the details of the UniquE implementation (in C), but here's a more general attribution;
-This would not have been possible without the GPL:d work of Christian Scheurer!
-
- Erik Larsson, 2007
diff --git a/src/org/catacombae/rarx/TestRAFProperties.java b/src/org/catacombae/rarx/TestRAFProperties.java
deleted file mode 100644
index ffbb955..0000000
--- a/src/org/catacombae/rarx/TestRAFProperties.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-public class TestRAFProperties {
- public static void main(String[] args) {
- //723152686 32768
- int number = 30197;
- System.out.println(number + " (0x" + Util.toHexStringBE(number) + ")");
- System.out.println((0-number) + " (0x" + Util.toHexStringBE((0-number)) + ")");
- System.out.println(((0-number) & 0xFFFFF) + " (0x" + Util.toHexStringBE(((0-number) & 0xFFFFF)) + ")");
- System.out.println((0xFFFFF-number) + " (0x" + Util.toHexStringBE((0xFFFFF-number)) + ")");
- }
-}
diff --git a/src/org/catacombae/rarx/Tree.java b/src/org/catacombae/rarx/Tree.java
deleted file mode 100644
index 1ec9eb0..0000000
--- a/src/org/catacombae/rarx/Tree.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.catacombae.rarx;
-import java.util.LinkedList;
-
-public class Tree<A> extends TreeNode<A> {
- public Tree(A value) { super(value); }
- public Tree() { super(); }
-
- private LinkedList<Pair<String, TreeNode<A>>> children = new LinkedList<Pair<String, TreeNode<A>>>();
-
- private static class Pair<A, B> {
- public A a;
- public B b;
- public Pair(A a, B b) {
- this.a = a;
- this.b = b;
- }
- }
-
- public void put(String entryName, TreeNode<A> tn) {
- children.addLast(new Pair<String, TreeNode<A>>(entryName, tn));
- }
- public TreeNode<A> get(String entryName) {
- for(Pair<String, TreeNode<A>> p : children) {
- if(p.a.equals(entryName))
- return p.b;
- }
- return null;
- }
-
- public int childCount() {
- return children.size();
- }
-
- public String[] listChildrenNames() {
- String[] targetArray = new String[children.size()];
- int i = 0;
- for(Pair<String, TreeNode<A>> p : children)
- targetArray[i++] = p.a;
-
- return targetArray;
-
- }
-
- public A[] listChildren(A[] targetArray) {
- if(targetArray.length != children.size())
- throw new IllegalArgumentException("target array not matching number of children");
- else {
- int i = 0;
- for(Pair<String, TreeNode<A>> p : children) {
- targetArray[i++] = p.b.getValue();
- }
- return targetArray;
- }
- }
-}
diff --git a/src/org/catacombae/rarx/TreeNode.java b/src/org/catacombae/rarx/TreeNode.java
deleted file mode 100644
index 1da80c9..0000000
--- a/src/org/catacombae/rarx/TreeNode.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.catacombae.rarx;
-
-public abstract class TreeNode<A> {
- private A value;
- public TreeNode(A value) {
- this.value = value;
- }
- public TreeNode() {
- this.value = null;
- }
- public A getValue() {
- return value;
- }
- public void setValue(A a) {
- value = a;
- }
-}
diff --git a/src/org/catacombae/rarx/UNIXFileAttributes.java b/src/org/catacombae/rarx/UNIXFileAttributes.java
deleted file mode 100644
index 175e8d2..0000000
--- a/src/org/catacombae/rarx/UNIXFileAttributes.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.io.PrintStream;
-
-public class UNIXFileAttributes implements FileAttributes {
- private int attributes;
-
- public UNIXFileAttributes(int attributes) {
- this.attributes = attributes;
- }
-
- public boolean isDirectory() { return isDirectoryFlagSet(); }
-
- public boolean isFileFlagSet() { return Util.getBit(attributes, 15); }
- public boolean isDirectoryFlagSet() { return Util.getBit(attributes, 14); }
- public boolean isSpecialFileFlagSet() { return Util.getBit(attributes, 13); }
- public boolean isOwnerReadFlagSet() { return Util.getBit(attributes, 8); }
- public boolean isOwnerWriteFlagSet() { return Util.getBit(attributes, 7); }
- public boolean isOwnerExecuteFlagSet() { return Util.getBit(attributes, 6); }
- public boolean isGroupReadFlagSet() { return Util.getBit(attributes, 5); }
- public boolean isGroupWriteFlagSet() { return Util.getBit(attributes, 4); }
- public boolean isGroupExecuteFlagSet() { return Util.getBit(attributes, 3); }
- public boolean isOthersReadFlagSet() { return Util.getBit(attributes, 2); }
- public boolean isOthersWriteFlagSet() { return Util.getBit(attributes, 1); }
- public boolean isOthersExecuteFlagSet() { return Util.getBit(attributes, 0); }
-
- public void print(PrintStream ps, String prefix) {
- ps.println(prefix + "UNIXFileAttributes:");
- printFields(ps, prefix);
- }
- public void printFields(PrintStream ps, String prefix) {
- ps.println(prefix + " isFileFlagSet: " + isFileFlagSet());
- ps.println(prefix + " isDirectoryFlagSet: " + isDirectoryFlagSet());
- ps.println(prefix + " isSpecialFileFlagSet: " + isSpecialFileFlagSet());
- ps.println(prefix + " isOwnerReadFlagSet: " + isOwnerReadFlagSet());
- ps.println(prefix + " isOwnerWriteFlagSet: " + isOwnerWriteFlagSet());
- ps.println(prefix + " isOwnerExecuteFlagSet: " + isOwnerExecuteFlagSet());
- ps.println(prefix + " isGroupReadFlagSet: " + isGroupReadFlagSet());
- ps.println(prefix + " isGroupWriteFlagSet: " + isGroupWriteFlagSet());
- ps.println(prefix + " isGroupExecuteFlagSet: " + isGroupExecuteFlagSet());
- ps.println(prefix + " isOthersReadFlagSet: " + isOthersReadFlagSet());
- ps.println(prefix + " isOthersWriteFlagSet: " + isOthersWriteFlagSet());
- ps.println(prefix + " isOthersExecuteFlagSet: " + isOthersExecuteFlagSet());
-// ps.println(prefix + " isFlagSet: " + isFlagSet());
- }
-}
diff --git a/src/org/catacombae/rarx/UnknownHeader.java b/src/org/catacombae/rarx/UnknownHeader.java
deleted file mode 100644
index 857ba4d..0000000
--- a/src/org/catacombae/rarx/UnknownHeader.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.io.PrintStream;
-
-public class UnknownHeader extends RARHeader {
- private final byte[] data;
-
- public UnknownHeader(byte[] inData, int offset) {
- super(inData, offset);
- data = new byte[getHeadSize()-super.getSize()];
- System.arraycopy(inData, super.getSize(), data, 0, data.length);
- super.validateData();
- }
-
- public int getSize() {
- return _getSize();
- }
- private int _getSize() {
- return super.getSize()+data.length;
- }
-
- public byte[] getHeaderData() {
- byte[] outData = new byte[_getSize()];
- byte[] superData = super.getHeaderData();
- System.arraycopy(superData, 0, outData, 0, superData.length);
- System.arraycopy(data, 0, outData, superData.length, data.length);
- return outData;
- }
-
- public void print(PrintStream ps, String prefix) {
- System.out.println("Unknown header:");
- printFields(ps, prefix);
- }
-}
diff --git a/src/org/catacombae/rarx/Util.java b/src/org/catacombae/rarx/Util.java
deleted file mode 100644
index 80cb47b..0000000
--- a/src/org/catacombae/rarx/Util.java
+++ /dev/null
@@ -1,305 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-public class Util {
- public static int sectorSize = 0x800;
-
- public static String byteArrayToHexString(byte[] array) {
- return byteArrayToHexString(array, 0, array.length);
- }
- public static String byteArrayToHexString(byte[] array, int offset, int length) {
- String result = "";
- for(int i = offset; i < (offset+length); ++i) {
- byte b = array[i];
- String currentHexString = Integer.toHexString(b & 0xFF);
- if(currentHexString.length() == 1)
- currentHexString = "0" + currentHexString;
- result += currentHexString;
- }
- return result;
- }
- public static String toHexStringBE(int[] array) {
- return toHexStringBE(array, 0, array.length);
- }
- public static String toHexStringBE(int[] array, int offset, int length) {
- StringBuilder result = new StringBuilder();
- for(int i : array)
- result.append(toHexStringBE(i));
- return result.toString();
- }
-
- public static String toHexStringLE(byte n) { return byteArrayToHexString(toByteArrayLE(n)); }
- public static String toHexStringLE(short n) { return byteArrayToHexString(toByteArrayLE(n)); }
- public static String toHexStringLE(int n) { return byteArrayToHexString(toByteArrayLE(n)); }
- public static String toHexStringLE(long n) { return byteArrayToHexString(toByteArrayLE(n)); }
- public static String toHexStringBE(byte n) { return byteArrayToHexString(toByteArrayBE(n)); }
- public static String toHexStringBE(short n) { return byteArrayToHexString(toByteArrayBE(n)); }
- public static String toHexStringBE(int n) { return byteArrayToHexString(toByteArrayBE(n)); }
- public static String toHexStringBE(long n) { return byteArrayToHexString(toByteArrayBE(n)); }
-
- public static byte[] invert(byte[] array) {
- byte[] newArray = new byte[array.length];
- for(int i = 0; i < array.length; ++i)
- newArray[newArray.length-i-1] = array[i];
- return newArray;
- }
-
- public static int readIntLE(byte[] data) {
- return readIntLE(data, 0);
- }
- public static int readIntLE(byte[] data, int offset) {
- return ((data[offset+3] & 0xFF) << 24 |
- (data[offset+2] & 0xFF) << 16 |
- (data[offset+1] & 0xFF) << 8 |
- (data[offset+0] & 0xFF) << 0);
- }
- public static short readShortLE(byte[] data) {
- return readShortLE(data, 0);
- }
- public static short readShortLE(byte[] data, int offset) {
- return (short) ((data[offset+1] & 0xFF) << 8 |
- (data[offset+0] & 0xFF) << 0);
- }
- public static byte readByteLE(byte[] data) {
- return readByteLE(data, 0);
- }
- public static byte readByteLE(byte[] data, int offset) {
- return data[offset];
- }
-
- public static byte[] toByteArrayLE(byte b) {
- byte[] result = new byte[1];
- result[0] = b;
- return result;
- }
- public static byte[] toByteArrayLE(short s) {
- byte[] result = new byte[2];
- result[0] = (byte) ((s >> 0) & 0xFF);
- result[1] = (byte) ((s >> 8) & 0xFF);
- return result;
- }
- public static byte[] toByteArrayLE(int i) {
- byte[] result = new byte[4];
- result[0] = (byte) ((i >> 0) & 0xFF);
- result[1] = (byte) ((i >> 8) & 0xFF);
- result[2] = (byte) ((i >> 16) & 0xFF);
- result[3] = (byte) ((i >> 24) & 0xFF);
- return result;
- }
- public static byte[] toByteArrayLE(long l) {
- byte[] result = new byte[8];
- result[0] = (byte) ((l >> 0) & 0xFF);
- result[1] = (byte) ((l >> 8) & 0xFF);
- result[2] = (byte) ((l >> 16) & 0xFF);
- result[3] = (byte) ((l >> 24) & 0xFF);
- result[4] = (byte) ((l >> 32) & 0xFF);
- result[5] = (byte) ((l >> 40) & 0xFF);
- result[6] = (byte) ((l >> 48) & 0xFF);
- result[7] = (byte) ((l >> 56) & 0xFF);
- return result;
- }
- public static byte[] toByteArrayBE(byte b) {
- byte[] result = new byte[1];
- result[0] = b;
- return result;
- }
- public static byte[] toByteArrayBE(short s) {
- byte[] result = new byte[2];
- result[0] = (byte) ((s >> 8) & 0xFF);
- result[1] = (byte) ((s >> 0) & 0xFF);
- return result;
- }
- public static byte[] toByteArrayBE(int i) {
- byte[] result = new byte[4];
- result[0] = (byte) ((i >> 24) & 0xFF);
- result[1] = (byte) ((i >> 16) & 0xFF);
- result[2] = (byte) ((i >> 8) & 0xFF);
- result[3] = (byte) ((i >> 0) & 0xFF);
- return result;
- }
- public static byte[] toByteArrayBE(long l) {
- byte[] result = new byte[8];
- result[0] = (byte) ((l >> 56) & 0xFF);
- result[1] = (byte) ((l >> 48) & 0xFF);
- result[2] = (byte) ((l >> 40) & 0xFF);
- result[3] = (byte) ((l >> 32) & 0xFF);
- result[4] = (byte) ((l >> 24) & 0xFF);
- result[5] = (byte) ((l >> 16) & 0xFF);
- result[6] = (byte) ((l >> 8) & 0xFF);
- result[7] = (byte) ((l >> 0) & 0xFF);
- return result;
- }
-
- public static boolean zeroed(byte[] ba) {
- for(byte b : ba)
- if(b != 0)
- return false;
- return true;
- }
-
- public static void zero(byte[] ba) {
- set(ba, 0, ba.length, (byte)0);
- }
- public static void zero(byte[] ba, int offset, int length) {
- set(ba, offset, length, (byte)0);
- }
- public static void zero(short[] ba) {
- set(ba, 0, ba.length, (short)0);
- }
- public static void zero(short[] ba, int offset, int length) {
- set(ba, offset, length, (short)0);
- }
- public static void zero(int[] ba) {
- set(ba, 0, ba.length, (int)0);
- }
- public static void zero(int[] ba, int offset, int length) {
- set(ba, offset, length, (int)0);
- }
- public static void zero(long[] ba) {
- set(ba, 0, ba.length, (long)0);
- }
- public static void zero(long[] ba, int offset, int length) {
- set(ba, offset, length, (long)0);
- }
-
- public static void set(byte[] ba, int offset, int length, byte value) {
- for(int i = offset; i < length; ++i)
- ba[i] = value;
- }
- public static void set(short[] ba, int offset, int length, short value) {
- for(int i = offset; i < length; ++i)
- ba[i] = value;
- }
- public static void set(int[] ba, int offset, int length, int value) {
- for(int i = offset; i < length; ++i)
- ba[i] = value;
- }
- public static void set(long[] ba, int offset, int length, long value) {
- for(int i = offset; i < length; ++i)
- ba[i] = value;
- }
-
- public static byte[] createCopy(byte[] data) {
- return createCopy(data, 0, data.length);
- }
-
- public static byte[] createCopy(byte[] data, int offset, int length) {
- byte[] copy = new byte[length];
- System.arraycopy(data, offset, copy, 0, length);
- return copy;
- }
-
- public static boolean arraysEqual(boolean[] a, boolean[] b) {
- if(a.length != b.length)
- return false;
- else {
- for(int i = 0; i < a.length; ++i)
- if(a[i] != b[i])
- return false;
- return true;
- }
- }
- public static boolean arraysEqual(byte[] a, byte[] b) {
- if(a.length != b.length)
- return false;
- else {
- for(int i = 0; i < a.length; ++i)
- if(a[i] != b[i])
- return false;
- return true;
- }
- }
- public static boolean arraysEqual(char[] a, char[] b) {
- if(a.length != b.length)
- return false;
- else {
- for(int i = 0; i < a.length; ++i)
- if(a[i] != b[i])
- return false;
- return true;
- }
- }
- public static boolean arraysEqual(short[] a, short[] b) {
- if(a.length != b.length)
- return false;
- else {
- for(int i = 0; i < a.length; ++i)
- if(a[i] != b[i])
- return false;
- return true;
- }
- }
- public static boolean arraysEqual(int[] a, int[] b) {
- if(a.length != b.length)
- return false;
- else {
- for(int i = 0; i < a.length; ++i)
- if(a[i] != b[i])
- return false;
- return true;
- }
- }
- public static boolean arraysEqual(long[] a, long[] b) {
- if(a.length != b.length)
- return false;
- else {
- for(int i = 0; i < a.length; ++i)
- if(a[i] != b[i])
- return false;
- return true;
- }
- }
- public static boolean arraysEqual(Object[] a, Object[] b) {
- if(a.length != b.length)
- return false;
- else {
- for(int i = 0; i < a.length; ++i)
- if(!a[i].equals(b[i]))
- return false;
- return true;
- }
- }
-
- public static long pow(long a, long b) {
- if(b < 0) throw new IllegalArgumentException("b can not be negative");
-
- long result = 1;
- for(long i = 0; i < b; ++i)
- result *= a;
- return result;
- }
-
- public static int strlen(byte[] data) {
- int length = 0;
- for(byte b : data) {
- if(b == 0)
- break;
- else
- ++length;
- }
- return length;
- }
-
- public static boolean getBit(long data, int bitNumber) {
- return ((data >>> bitNumber) & 0x1) == 0x1;
- }
-}
diff --git a/src/org/catacombae/rarx/Win32FileAttributes.java b/src/org/catacombae/rarx/Win32FileAttributes.java
deleted file mode 100644
index 957f40a..0000000
--- a/src/org/catacombae/rarx/Win32FileAttributes.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*-
- * Copyright (C) 2006 Erik Larsson
- *
- * All rights reserved.
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-package org.catacombae.rarx;
-
-import java.io.PrintStream;
-
-public class Win32FileAttributes implements FileAttributes {
- private int attributes;
-
- public Win32FileAttributes(int attributes) {
- this.attributes = attributes;
- }
-
- // Inteface methods
- public boolean isDirectory() {
- return isDirectoryFlagSet();
- }
-
- public boolean isReadOnlyFlagSet() {
- return Util.getBit(attributes, 0);
- }
- public boolean isHiddenFlagSet() {
- return Util.getBit(attributes, 1);
- }
- public boolean isSystemFlagSet() {
- return Util.getBit(attributes, 2);
- }
- public boolean isLabelFlagSet() {
- return Util.getBit(attributes, 3);
- }
- public boolean isDirectoryFlagSet() {
- return Util.getBit(attributes, 4);
- }
- public boolean isArchiveFlagSet() {
- return Util.getBit(attributes, 5);
- }
-
- public void print(PrintStream ps, String prefix) {
- ps.println(prefix + "Win32FileAttributes:");
- printFields(ps, prefix);
- }
- public void printFields(PrintStream ps, String prefix) {
- ps.println(prefix + " isReadOnlyFlagSet: " + isReadOnlyFlagSet());
- ps.println(prefix + " isHiddenFlagSet: " + isHiddenFlagSet());
- ps.println(prefix + " isSystemFlagSet: " + isSystemFlagSet());
- ps.println(prefix + " isLabelFlagSet: " + isLabelFlagSet());
- ps.println(prefix + " isDirectoryFlagSet: " + isDirectoryFlagSet());
- ps.println(prefix + " isArchiveFlagSet: " + isArchiveFlagSet());
- }
-}