From 907508ecbe43f28f14cf773b3b5d8a7a977d9c67 Mon Sep 17 00:00:00 2001 From: emile Date: Fri, 30 Jan 2004 07:38:42 +0000 Subject: [PATCH] 2003/09/29 01:41:51 darcs-hash:20040130073842-22ae6-befbd03d020687eb2de18373cfea0654ad66ea71.gz --- src/org/xwt/Res.java | 10 +++- src/org/xwt/util/CAB.java | 119 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 108 insertions(+), 21 deletions(-) diff --git a/src/org/xwt/Res.java b/src/org/xwt/Res.java index 862b12d..01856f2 100644 --- a/src/org/xwt/Res.java +++ b/src/org/xwt/Res.java @@ -173,7 +173,7 @@ public abstract class Res extends JS { return ((i & 0xff) << 24) | ((i & 0xff00) << 8) | ((i & 0xff0000) >>> 8) | (i >>> 24); } public InputStream getInputStream(String path) throws IOException { - InputStream is = parent.getInputStream(); + /* InputStream is = parent.getInputStream(); byte[] scan = new byte[4]; int ofs = 0; for(int i=0; i<2; i++) { @@ -189,6 +189,14 @@ public abstract class Res extends JS { } Log.log(this, "found MSCF header at offset " + ofs); return org.xwt.util.CAB.getFileInputStream(is, path, true); + */ + try { + return org.xwt.util.CAB.getFileInputStream(is, 2, path); + } catch (EOFException eof) { + throw new JS.Exn("MSCF header tag not found in file"); + } catch (EOFException eof) { + throw new JS.Exn("IOException while reading file"); + } } } 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 */ -- 1.7.10.4