From 4ed357774aa94ad8be60ec9d257cc414462a0dc6 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 19 Oct 2012 11:32:57 +0400 Subject: switch to junrar library --- src/org/catacombae/rarx/NewFileHeader.java | 428 ----------------------------- 1 file changed, 428 deletions(-) delete mode 100644 src/org/catacombae/rarx/NewFileHeader.java (limited to 'src/org/catacombae/rarx/NewFileHeader.java') 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 codeUnitList = new LinkedList(); - - // 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> 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); - } -} -- cgit v1.2.3