X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2Futil%2FCAB.java;h=a74b47f138030257760366cd2f3d75d21598cc0b;hb=de378041d5ca2aca1a2b5a31ef15ae90a86c977f;hp=529bdae466bfebace0a2f9adc4a76fc5a5d5bf95;hpb=d9fdc968988212807221d0d71d2fb6dc19cb87a3;p=org.ibex.core.git diff --git a/src/org/xwt/util/CAB.java b/src/org/xwt/util/CAB.java index 529bdae..a74b47f 100644 --- a/src/org/xwt/util/CAB.java +++ b/src/org/xwt/util/CAB.java @@ -1,4 +1,10 @@ -// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL] +// Copyright (C) 2003 Adam Megacz all rights reserved. +// +// You may modify, copy, and redistribute this code under the terms of +// the GNU Library Public License version 2.1, with the exception of +// the portion of clause 6a after the semicolon (aka the "obnoxious +// relink clause") + package org.xwt.util; import java.io.*; @@ -10,14 +16,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 IOException {} } /** 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 +259,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 IOException { + private int compressionType; + + UnsupportedCompressionTypeException(int type) { + compressionType = type; + } + public String toString() { + return "UnsupportedCompressionTypeException: no support for compression type " + compressionName(compressionType); + } + } } /** Encapsulates a CFFILE entry */