X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2Futil%2FCAB.java;h=b76337d1726dcaca113ec9cf24109f9a86d421d4;hb=907508ecbe43f28f14cf773b3b5d8a7a977d9c67;hp=529bdae466bfebace0a2f9adc4a76fc5a5d5bf95;hpb=574af437a07d0e80428923a4004f3d7c1b1be7e2;p=org.ibex.core.git diff --git a/src/org/xwt/util/CAB.java b/src/org/xwt/util/CAB.java index 529bdae..b76337d 100644 --- a/src/org/xwt/util/CAB.java +++ b/src/org/xwt/util/CAB.java @@ -10,14 +10,29 @@ import java.math.*; public class CAB { /** reads a CAB file, parses it, and returns an InputStream representing the named file */ - public static InputStream getFileInputStream(InputStream is, String fileName, boolean mscfAlreadyConsumed) throws IOException { + public static InputStream getFileInputStream(InputStream is, String fileName) throws IOException, EOFException { + return getFileInputStream(is, 0, fileName); + } + + public static InputStream getFileInputStream(InputStream is, int skipHeaders, String fileName) throws IOException, EOFException { DataInputStream dis = new DataInputStream(is); CFHEADER h = new CFHEADER(); - h.read(dis, mscfAlreadyConsumed); + + while (skipHeaders > 0) { CFHEADER.seekMSCF(dis); skipHeaders--; } + + try { + h.read(dis); + } catch (CFHEADER.BogusHeaderException bhe) { + throw new EOFException(); + } for(int i=0; i 0) dis.readFully(perCabinetReservedArea); } - if (prevCAB) { - previousCabinet = readZeroTerminatedString(dis); - previousDisk = readZeroTerminatedString(dis); - } - if (nextCAB) { - nextCabinet = readZeroTerminatedString(dis); - nextDisk = readZeroTerminatedString(dis); + + try { + if (prevCAB) { + previousCabinet = readZeroTerminatedString(dis); + previousDisk = readZeroTerminatedString(dis); + } + if (nextCAB) { + nextCabinet = readZeroTerminatedString(dis); + nextDisk = readZeroTerminatedString(dis); + } + } catch (ArrayIndexOutOfBoundsException e) { + throw new BogusHeaderException(); } } + + public static void seekMSCF(DataInputStream dis) throws EOFException, IOException + { + int state; + // skip up to and including the 'MSCF' signature + state = 0; + while (state != 4) { + // M + while (state == 0 && dis.readByte() != 0x4D) { } + state = 1; + // S + switch (dis.readByte()) { + case 0x53 : state = 2; break; + case 0x4D : state = 1; continue; + default : state = 0; continue; + } + // C + if (dis.readByte() == 0x43) { state = 3; } + else { state = 0; continue; } + // F + if (dis.readByte() == 0x46) { state = 4; } + else { state = 0; } + } + } + + public static class BogusHeaderException extends Exception {} } /** Encapsulates a CFFOLDER entry */ public static class CFFOLDER { + public static final int COMPRESSION_NONE = 0; + public static final int COMPRESSION_MSZIP = 1; + public static final int COMPRESSION_QUANTUM = 2; + public static final int COMPRESSION_LZX = 3; + int firstBlockOffset = 0; // offset of first data block within this folder int numBlocks = 0; // number of data blocks int compressionType = 0; // compression type for this folder @@ -203,19 +253,48 @@ public class CAB { public String toString() { return "[ CAB CFFOLDER, " + numBlocks + " data blocks, compression type " + - (compressionType == 1 ? "MSZIP" : "unknown") + + compressionName(compressionType) + ", " + reservedArea.length + " bytes of reserved data ]"; } - public void read(DataInputStream dis) throws IOException { + public void read(DataInputStream dis) throws IOException, UnsupportedCompressionTypeException { firstBlockOffset = readLittleInt(dis); numBlocks = readLittleShort(dis); - compressionType = readLittleShort(dis); + compressionType = readLittleShort(dis) & 0x000F; + if (compressionType != COMPRESSION_MSZIP) { + throw new UnsupportedCompressionTypeException(compressionType); + } reservedArea = new byte[header.perCFFOLDERReservedSize]; if (reservedArea.length > 0) dis.readFully(reservedArea); indexInCFHEADER = header.readCFFOLDERs++; header.folders[indexInCFHEADER] = this; } + + public static String compressionName(int type) { + switch (type) { + case COMPRESSION_NONE: + return "NONE"; + case COMPRESSION_MSZIP: + return "MSZIP"; + case COMPRESSION_QUANTUM: + return "QUANTUM"; + case COMPRESSION_LZX: + return "LZX"; + default: + return ""; + } + } + + public static class UnsupportedCompressionTypeException extends Exception { + private int compressionType; + + UnsupportedCompressionTypeException(int type) { + compressionType = type; + } + public String toString() { + return "UnsupportedCompressionTypeException: no support for compression type " + compressionName(compressionType); + } + } } /** Encapsulates a CFFILE entry */