⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unpack.java

📁 java下操作rar文件,创建,压缩/解压缩等等.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
 * Original author: Edmund Wagner
 * Creation date: 31.05.2007
 *
 * Source: $HeadURL$
 * Last changed: $LastChangedDate$
 * 
 * the unrar licence applies to all junrar source and binary distributions 
 * you are not allowed to use this source to re-create the RAR compression algorithm
 * 
 * Here some html entities which can be used for escaping javadoc tags:
 * "&":  "&" or "&"
 * "<":  "&#060;" or "&lt;"
 * ">":  "&#062;" or "&gt;"
 * "@":  "&#064;" 
 */
package de.innosystec.unrar.unpack;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;

import de.innosystec.unrar.exception.RarException;
import de.innosystec.unrar.exception.RarException.RarExceptionType;
import de.innosystec.unrar.unpack.decode.Compress;
import de.innosystec.unrar.unpack.ppm.BlockTypes;
import de.innosystec.unrar.unpack.ppm.ModelPPM;
import de.innosystec.unrar.unpack.vm.BitInput;
import de.innosystec.unrar.unpack.vm.RarVM;
import de.innosystec.unrar.unpack.vm.VMPreparedProgram;

/**
 * DOCUMENT ME
 * 
 * @author $LastChangedBy$
 * @version $LastChangedRevision$
 */
public final class Unpack extends Unpack20
{

	private ModelPPM ppm = new ModelPPM();

	private int ppmEscChar;

	private RarVM rarVM = new RarVM();

	/* Filters code, one entry per filter */
	private List<UnpackFilter> filters = new ArrayList<UnpackFilter>();

	/* Filters stack, several entrances of same filter are possible */
	private List<UnpackFilter> prgStack = new ArrayList<UnpackFilter>();

	/*
	 * lengths of preceding blocks, one length per filter. Used to reduce size
	 * required to write block length if lengths are repeating
	 */
	private List<Integer> oldFilterLengths = new ArrayList<Integer>();

	private int lastFilter;

	private boolean tablesRead;

	private byte[] unpOldTable = new byte[Compress.HUFF_TABLE_SIZE];

	private BlockTypes unpBlockType;

	private boolean externalWindow;

	private long writtenFileSize;

	private boolean fileExtracted;

	private boolean ppmError;

	private int prevLowDist;

	private int lowDistRepCount;

	public static int[] DBitLengthCounts = { 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
			2, 2, 2, 2, 2, 14, 0, 12 };

	public Unpack(ComprDataIO DataIO)
	{
		unpIO = DataIO;
		window = null;
		externalWindow = false;
		suspended = false;
		unpAllBuf = false;
		unpSomeRead = false;
	}

	public void init(byte[] window)
	{
		if (window == null) {
			this.window = new byte[Compress.MAXWINSIZE];
		} else {
			this.window = window;
			externalWindow = true;
		}
		inAddr = 0;
		unpInitData(false);
	}

	public void doUnpack(int method, boolean solid) throws IOException, RarException
	{
		if (unpIO.getSubHeader().getUnpMethod() == 0x30) {
			unstoreFile();
		}
		switch (method) {
		case 15: // rar 1.5 compression
			unpack15(solid);
			break;
		case 20: // rar 2.x compression
		case 26: // files larger than 2GB
			unpack20(solid);
			break;
		case 29: // rar 3.x compression
		case 36: // alternative hash
			unpack29(solid);
			break;
		}
	}

	private void unstoreFile() throws IOException, RarException
	{
		byte[] buffer = new byte[0x10000];
		while (true) {
			int Code = unpIO.unpRead(buffer, 0, buffer.length);
			if (Code == 0 || (int) Code == -1)
				break;
			Code = Code < destUnpSize ? Code : (int) (destUnpSize);
			unpIO.unpWrite(buffer, 0, Code);
			if (destUnpSize >= 0)
				destUnpSize -= Code;
		}

	}

	private void unpack29(boolean solid) throws IOException, RarException
	{

		int[] DDecode = new int[Compress.DC];
		byte[] DBits = new byte[Compress.DC];

		int Bits;

		if (DDecode[1] == 0) {
			int Dist = 0, BitLength = 0, Slot = 0;
			for (int I = 0; I < DBitLengthCounts.length; I++, BitLength++) {
				for (int J = 0; J < DBitLengthCounts[I]; J++, Slot++, Dist += (1 << BitLength)) {
					DDecode[Slot] = Dist;
					DBits[Slot] = (byte) BitLength;
				}
			}
		}

		fileExtracted = true;

		if (!suspended) {
			unpInitData(solid);
			if (!unpReadBuf()) {
				return;
			}
			if ((!solid || !tablesRead) && !readTables()) {
				return;
			}
		}

		if (ppmError) {
			return;
		}

		while (true) {
			unpPtr &= Compress.MAXWINMASK;

			if (inAddr > readBorder) {
				if (!unpReadBuf()) {
					break;
				}
			}
			//System.out.println(((wrPtr - unpPtr) & Compress.MAXWINMASK)+":"+wrPtr+":"+unpPtr);
			if (((wrPtr - unpPtr) & Compress.MAXWINMASK) < 260
					&& wrPtr != unpPtr) {

				UnpWriteBuf();
				if (writtenFileSize > destUnpSize) {
					return;
				}
				if (suspended) {
					fileExtracted = false;
					return;
				}
			}
			if (unpBlockType == BlockTypes.BLOCK_PPM) {
		
				if(true){
					throw new RarException(RarExceptionType.notImplementedYet);
				}
				
				int Ch = ppm.decodeChar();
				if (Ch == -1) {
					ppmError = true;
					break;
				}
				if (Ch == ppmEscChar) {
					int NextCh = ppm.decodeChar();
					if (NextCh == 0) {
						if (!readTables()) {
							break;
						}
						continue;
					}
					if (NextCh == 2 || NextCh == -1) {
						break;
					}
					if (NextCh == 3) {
						if (!readVMCodePPM()) {
							break;
						}
						continue;
					}
					if (NextCh == 4) {
						int Distance = 0, Length = 0;
						boolean failed = false;
						for (int I = 0; I < 4 && !failed; I++) {
							int ch = ppm.decodeChar();
							if (ch == -1) {
								failed = true;
							} else {
								if (I == 3) {
									Length = (byte) ch;
								} else {
									Distance = (Distance << 8) + (byte) ch;
								}
							}
						}
						if (failed) {
							break;
						}
						copyString(Length + 32, Distance + 2);
						continue;
					}
					if (NextCh == 5) {
						int Length = ppm.decodeChar();
						if (Length == -1) {
							break;
						}
						copyString(Length + 4, 1);
						continue;
					}
				}
				window[unpPtr++] = (byte) Ch;
				continue;
			}

			int Number = decodeNumber(LD);
			if (Number < 256) {
				window[unpPtr++] = (byte) Number;
				continue;
			}
			if (Number >= 271) {
				int Length = LDecode[Number -= 271] + 3;
				if ((Bits = LBits[Number]) > 0) {
					Length += getbits() >>> (16 - Bits);
					addbits(Bits);
				}

				int DistNumber = decodeNumber(DD);
				int Distance = DDecode[DistNumber] + 1;
				if ((Bits = DBits[DistNumber]) > 0) {
					if (DistNumber > 9) {
						if (Bits > 4) {
							Distance += ((getbits() >>> (20 - Bits)) << 4);
							addbits(Bits - 4);
						}
						if (lowDistRepCount > 0) {
							lowDistRepCount--;
							Distance += prevLowDist;
						} else {
							int LowDist = decodeNumber(LDD);
							if (LowDist == 16) {
								lowDistRepCount = Compress.LOW_DIST_REP_COUNT - 1;
								Distance += prevLowDist;
							} else {
								Distance += LowDist;
								prevLowDist = LowDist;
							}
						}
					} else {
						Distance += getbits() >>> (16 - Bits);
						addbits(Bits);
					}
				}

				if (Distance >= 0x2000) {
					Length++;
					if (Distance >= 0x40000L) {
						Length++;
					}
				}

				insertOldDist(Distance);
				insertLastMatch(Length, Distance);

				copyString(Length, Distance);
				continue;
			}
			if (Number == 256) {
				if (!readEndOfBlock()) {
					break;
				}
				continue;
			}
			if (Number == 257) {
				if (!readVMCode()) {
					break;
				}
				continue;
			}
			if (Number == 258) {
				if (lastLength != 0) {
					copyString(lastLength, lastDist);
				}
				continue;
			}
			if (Number < 263) {
				int DistNum = Number - 259;
				int Distance = oldDist[DistNum];
				for (int I = DistNum; I > 0; I--) {
					oldDist[I] = oldDist[I - 1];
				}
				oldDist[0] = Distance;

				int LengthNumber = decodeNumber(RD);
				int Length = LDecode[LengthNumber] + 2;
				if ((Bits = LBits[LengthNumber]) > 0) {
					Length += getbits() >>> (16 - Bits);
					addbits(Bits);
				}
				insertLastMatch(Length, Distance);
				copyString(Length, Distance);
				continue;
			}
			if (Number < 272) {
				int Distance = SDDecode[Number -= 263] + 1;
				if ((Bits = SDBits[Number]) > 0) {
					Distance += getbits() >>> (16 - Bits);
					addbits(Bits);
				}
				insertOldDist(Distance);
				insertLastMatch(2, Distance);
				copyString(2, Distance);
				continue;
			}
		}
		UnpWriteBuf();

	}

	private void UnpWriteBuf() throws IOException
	{
		int WrittenBorder = wrPtr;
		int WriteSize = (unpPtr - WrittenBorder) & Compress.MAXWINMASK;
		for (int I = 0; I < prgStack.size(); I++) {
			UnpackFilter flt = prgStack.get(I);
			if (flt == null) {
				continue;
			}
			if (flt.isNextWindow()) {
				flt.setNextWindow(false);// ->NextWindow=false;
				continue;
			}
			int BlockStart = flt.getBlockStart();// ->BlockStart;
			int BlockLength = flt.getBlockLength();// ->BlockLength;
			if (((BlockStart - WrittenBorder) & Compress.MAXWINMASK) < WriteSize) {
				if (WrittenBorder != BlockStart) {
					UnpWriteArea(WrittenBorder, BlockStart);
					WrittenBorder = BlockStart;
					WriteSize = (unpPtr - WrittenBorder) & Compress.MAXWINMASK;
				}
				if (BlockLength <= WriteSize) {
					int BlockEnd = (BlockStart + BlockLength)
							& Compress.MAXWINMASK;
					if (BlockStart < BlockEnd || BlockEnd == 0) {
						// VM.SetMemory(0,Window+BlockStart,BlockLength);
						rarVM.setMemory(0, window, BlockStart, BlockLength);
					} else {
						int FirstPartLength = Compress.MAXWINSIZE - BlockStart;
						// VM.SetMemory(0,Window+BlockStart,FirstPartLength);
						rarVM.setMemory(0, window, BlockStart, FirstPartLength);
						// VM.SetMemory(FirstPartLength,Window,BlockEnd);
						rarVM.setMemory(FirstPartLength, window, 0, BlockEnd);

					}

					VMPreparedProgram ParentPrg = filters.get(
							flt.getParentFilter()).getPrg();
					VMPreparedProgram Prg = flt.getPrg();

					if (ParentPrg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) {
						// copy global data from previous script execution if
						// any
						// Prg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
						// memcpy(&Prg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
						Prg.getGlobalData().setSize(
								ParentPrg.getGlobalData().size());
						for (int i = 0; i < ParentPrg.getGlobalData().size()
								- RarVM.VM_FIXEDGLOBALSIZE; i++) {
							Prg.getGlobalData().set(
									RarVM.VM_FIXEDGLOBALSIZE + i,
									ParentPrg.getGlobalData().get(
											RarVM.VM_FIXEDGLOBALSIZE + i));
						}
					}

					ExecuteCode(Prg);

					if (Prg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) {
						// save global data for next script execution
						if (ParentPrg.getGlobalData().size() < Prg
								.getGlobalData().size()) {
							ParentPrg.getGlobalData().setSize(
									Prg.getGlobalData().size());// ->GlobalData.Alloc(Prg->GlobalData.Size());
						}
						// memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&Prg->GlobalData[VM_FIXEDGLOBALSIZE],Prg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
						for (int i = 0; i < Prg.getGlobalData().size()
								- RarVM.VM_FIXEDGLOBALSIZE; i++) {
							ParentPrg.getGlobalData().set(
									RarVM.VM_FIXEDGLOBALSIZE + i,
									Prg.getGlobalData().get(
											RarVM.VM_FIXEDGLOBALSIZE + i));
						}
					} else {
						ParentPrg.getGlobalData().clear();
					}

					int FilteredDataOffset = Prg.getFilteredDataOffset();
					int FilteredDataSize = Prg.getFilteredDataSize();
					byte[] FilteredData = new byte[FilteredDataSize];

					for (int i = 0; i < FilteredDataSize; i++) {
						FilteredData[i] = rarVM.getMem()[FilteredDataOffset+i];//Prg.getGlobalData().get(FilteredDataOffset + i);
					}

					prgStack.set(I, null);
					while (I + 1 < prgStack.size()) {
						UnpackFilter NextFilter = prgStack.get(I + 1);
						if (NextFilter == null
								|| NextFilter.getBlockStart() != BlockStart
								|| NextFilter.getBlockLength() != FilteredDataSize
								|| NextFilter.isNextWindow()) {
							break;
						}
						// apply several filters to same data block

						rarVM.setMemory(0, FilteredData, 0, FilteredDataSize);// .SetMemory(0,FilteredData,FilteredDataSize);

						VMPreparedProgram pPrg = filters.get(
								NextFilter.getParentFilter()).getPrg();
						VMPreparedProgram NextPrg = NextFilter.getPrg();

						if (pPrg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) {
							// copy global data from previous script execution
							// if any
							// NextPrg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
							NextPrg.getGlobalData().setSize(
									pPrg.getGlobalData().size());
							// memcpy(&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
							for (int i = 0; i < pPrg.getGlobalData().size()
									- RarVM.VM_FIXEDGLOBALSIZE; i++) {
								NextPrg.getGlobalData().set(
										RarVM.VM_FIXEDGLOBALSIZE + i,
										pPrg.getGlobalData().get(
												RarVM.VM_FIXEDGLOBALSIZE + i));
							}
						}

						ExecuteCode(NextPrg);

						if (NextPrg.getGlobalData().size() > RarVM.VM_FIXEDGLOBALSIZE) {
							// save global data for next script execution
							if (pPrg.getGlobalData().size() < NextPrg
									.getGlobalData().size()) {
								pPrg.getGlobalData().setSize(
										NextPrg.getGlobalData().size());
							}
							// memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],NextPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
							for (int i = 0; i < NextPrg.getGlobalData().size()
									- RarVM.VM_FIXEDGLOBALSIZE; i++) {
								pPrg.getGlobalData().set(
										RarVM.VM_FIXEDGLOBALSIZE + i,
										NextPrg.getGlobalData().get(
												RarVM.VM_FIXEDGLOBALSIZE + i));
							}
						} else {
							pPrg.getGlobalData().clear();
						}
						FilteredDataOffset = NextPrg.getFilteredDataOffset();
						FilteredDataSize = NextPrg.getFilteredDataSize();

						FilteredData = new byte[FilteredDataSize];
						for (int i = 0; i < FilteredDataSize; i++) {
							FilteredData[i] = NextPrg.getGlobalData().get(
									FilteredDataOffset + i);
						}

						I++;
						prgStack.set(I, null);
					}
					unpIO.unpWrite(FilteredData, 0, FilteredDataSize);
					unpSomeRead = true;
					writtenFileSize += FilteredDataSize;
					WrittenBorder = BlockEnd;
					WriteSize = (unpPtr - WrittenBorder) & Compress.MAXWINMASK;
				} else {
					for (int J = I; J < prgStack.size(); J++) {
						UnpackFilter filt = prgStack.get(J);
						if (filt != null && filt.isNextWindow()) {
							filt.setNextWindow(false);
						}
					}
					wrPtr = WrittenBorder;
					return;
				}
			}
		}

		UnpWriteArea(WrittenBorder, unpPtr);
		wrPtr = unpPtr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -