first commit
This commit is contained in:
266
hrmsEjb/jxl/read/biff/CompoundFile.java
Normal file
266
hrmsEjb/jxl/read/biff/CompoundFile.java
Normal file
@@ -0,0 +1,266 @@
|
||||
package jxl.read.biff;
|
||||
|
||||
import common.Logger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import jxl.WorkbookSettings;
|
||||
import jxl.biff.BaseCompoundFile;
|
||||
import jxl.biff.IntegerHelper;
|
||||
|
||||
public final class CompoundFile extends BaseCompoundFile {
|
||||
private static Logger logger = Logger.getLogger(CompoundFile.class);
|
||||
|
||||
private byte[] data;
|
||||
|
||||
private int numBigBlockDepotBlocks;
|
||||
|
||||
private int sbdStartBlock;
|
||||
|
||||
private int rootStartBlock;
|
||||
|
||||
private int extensionBlock;
|
||||
|
||||
private int numExtensionBlocks;
|
||||
|
||||
private byte[] rootEntry;
|
||||
|
||||
private int[] bigBlockChain;
|
||||
|
||||
private int[] smallBlockChain;
|
||||
|
||||
private int[] bigBlockDepotBlocks;
|
||||
|
||||
private ArrayList propertySets;
|
||||
|
||||
private WorkbookSettings settings;
|
||||
|
||||
private BaseCompoundFile.PropertyStorage rootEntryPropertyStorage;
|
||||
|
||||
public CompoundFile(byte[] d, WorkbookSettings ws) throws BiffException {
|
||||
this.data = d;
|
||||
this.settings = ws;
|
||||
for (int i = 0; i < IDENTIFIER.length; i++) {
|
||||
if (this.data[i] != IDENTIFIER[i])
|
||||
throw new BiffException(BiffException.unrecognizedOLEFile);
|
||||
}
|
||||
this.propertySets = new ArrayList();
|
||||
this.numBigBlockDepotBlocks = IntegerHelper.getInt(this.data[44], this.data[45], this.data[46], this.data[47]);
|
||||
this.sbdStartBlock = IntegerHelper.getInt(this.data[60], this.data[61], this.data[62], this.data[63]);
|
||||
this.rootStartBlock = IntegerHelper.getInt(this.data[48], this.data[49], this.data[50], this.data[51]);
|
||||
this.extensionBlock = IntegerHelper.getInt(this.data[68], this.data[69], this.data[70], this.data[71]);
|
||||
this.numExtensionBlocks = IntegerHelper.getInt(this.data[72], this.data[73], this.data[74], this.data[75]);
|
||||
this.bigBlockDepotBlocks = new int[this.numBigBlockDepotBlocks];
|
||||
int pos = 76;
|
||||
int bbdBlocks = this.numBigBlockDepotBlocks;
|
||||
if (this.numExtensionBlocks != 0)
|
||||
bbdBlocks = 109;
|
||||
for (int k = 0; k < bbdBlocks; k++) {
|
||||
this.bigBlockDepotBlocks[k] = IntegerHelper.getInt(d[pos], d[pos + 1], d[pos + 2], d[pos + 3]);
|
||||
pos += 4;
|
||||
}
|
||||
for (int j = 0; j < this.numExtensionBlocks; j++) {
|
||||
pos = (this.extensionBlock + 1) * 512;
|
||||
int blocksToRead = Math.min(this.numBigBlockDepotBlocks - bbdBlocks, 127);
|
||||
for (int m = bbdBlocks; m < bbdBlocks + blocksToRead; m++) {
|
||||
this.bigBlockDepotBlocks[m] = IntegerHelper.getInt(d[pos], d[pos + 1], d[pos + 2], d[pos + 3]);
|
||||
pos += 4;
|
||||
}
|
||||
bbdBlocks += blocksToRead;
|
||||
if (bbdBlocks < this.numBigBlockDepotBlocks)
|
||||
this.extensionBlock = IntegerHelper.getInt(d[pos], d[pos + 1], d[pos + 2], d[pos + 3]);
|
||||
}
|
||||
readBigBlockDepot();
|
||||
readSmallBlockDepot();
|
||||
this.rootEntry = readData(this.rootStartBlock);
|
||||
readPropertySets();
|
||||
}
|
||||
|
||||
private void readBigBlockDepot() {
|
||||
int pos = 0;
|
||||
int index = 0;
|
||||
this.bigBlockChain = new int[this.numBigBlockDepotBlocks * 512 / 4];
|
||||
for (int i = 0; i < this.numBigBlockDepotBlocks; i++) {
|
||||
pos = (this.bigBlockDepotBlocks[i] + 1) * 512;
|
||||
for (int j = 0; j < 128; j++) {
|
||||
this.bigBlockChain[index] = IntegerHelper.getInt(this.data[pos], this.data[pos + 1], this.data[pos + 2], this.data[pos + 3]);
|
||||
pos += 4;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readSmallBlockDepot() {
|
||||
int pos = 0;
|
||||
int index = 0;
|
||||
int sbdBlock = this.sbdStartBlock;
|
||||
this.smallBlockChain = new int[0];
|
||||
if (sbdBlock == -1) {
|
||||
logger.warn("invalid small block depot number");
|
||||
return;
|
||||
}
|
||||
while (sbdBlock != -2) {
|
||||
int[] oldChain = this.smallBlockChain;
|
||||
this.smallBlockChain = new int[this.smallBlockChain.length + 128];
|
||||
System.arraycopy(oldChain, 0, this.smallBlockChain, 0, oldChain.length);
|
||||
pos = (sbdBlock + 1) * 512;
|
||||
for (int j = 0; j < 128; j++) {
|
||||
this.smallBlockChain[index] = IntegerHelper.getInt(this.data[pos], this.data[pos + 1], this.data[pos + 2], this.data[pos + 3]);
|
||||
pos += 4;
|
||||
index++;
|
||||
}
|
||||
sbdBlock = this.bigBlockChain[sbdBlock];
|
||||
}
|
||||
}
|
||||
|
||||
private void readPropertySets() {
|
||||
int offset = 0;
|
||||
byte[] d = null;
|
||||
while (offset < this.rootEntry.length) {
|
||||
d = new byte[128];
|
||||
System.arraycopy(this.rootEntry, offset, d, 0, d.length);
|
||||
BaseCompoundFile.PropertyStorage ps = new BaseCompoundFile.PropertyStorage(this, d);
|
||||
if (ps.name == null || ps.name.length() == 0)
|
||||
if (ps.type == 5) {
|
||||
ps.name = "Root Entry";
|
||||
logger.warn("Property storage name for " + ps.type + " is empty - setting to " + "Root Entry");
|
||||
} else if (ps.size != 0) {
|
||||
logger.warn("Property storage type " + ps.type + " is non-empty and has no associated name");
|
||||
}
|
||||
this.propertySets.add(ps);
|
||||
if (ps.name.equalsIgnoreCase("Root Entry"))
|
||||
this.rootEntryPropertyStorage = ps;
|
||||
offset += 128;
|
||||
}
|
||||
if (this.rootEntryPropertyStorage == null)
|
||||
this.rootEntryPropertyStorage = this.propertySets.get(0);
|
||||
}
|
||||
|
||||
public byte[] getStream(String streamName) throws BiffException {
|
||||
BaseCompoundFile.PropertyStorage ps = findPropertyStorage(streamName, this.rootEntryPropertyStorage);
|
||||
if (ps == null)
|
||||
ps = getPropertyStorage(streamName);
|
||||
if (ps.size >= 4096 || streamName.equalsIgnoreCase("Root Entry"))
|
||||
return getBigBlockStream(ps);
|
||||
return getSmallBlockStream(ps);
|
||||
}
|
||||
|
||||
public byte[] getStream(int psIndex) throws BiffException {
|
||||
BaseCompoundFile.PropertyStorage ps = getPropertyStorage(psIndex);
|
||||
if (ps.size >= 4096 || ps.name.equalsIgnoreCase("Root Entry"))
|
||||
return getBigBlockStream(ps);
|
||||
return getSmallBlockStream(ps);
|
||||
}
|
||||
|
||||
public BaseCompoundFile.PropertyStorage findPropertyStorage(String name) {
|
||||
return findPropertyStorage(name, this.rootEntryPropertyStorage);
|
||||
}
|
||||
|
||||
private BaseCompoundFile.PropertyStorage findPropertyStorage(String name, BaseCompoundFile.PropertyStorage base) {
|
||||
if (base.child == -1)
|
||||
return null;
|
||||
BaseCompoundFile.PropertyStorage child = getPropertyStorage(base.child);
|
||||
if (child.name.equalsIgnoreCase(name))
|
||||
return child;
|
||||
BaseCompoundFile.PropertyStorage prev = child;
|
||||
while (prev.previous != -1) {
|
||||
prev = getPropertyStorage(prev.previous);
|
||||
if (prev.name.equalsIgnoreCase(name))
|
||||
return prev;
|
||||
}
|
||||
BaseCompoundFile.PropertyStorage next = child;
|
||||
while (next.next != -1) {
|
||||
next = getPropertyStorage(next.next);
|
||||
if (next.name.equalsIgnoreCase(name))
|
||||
return next;
|
||||
}
|
||||
return findPropertyStorage(name, child);
|
||||
}
|
||||
|
||||
private BaseCompoundFile.PropertyStorage getPropertyStorage(String name) throws BiffException {
|
||||
Iterator i = this.propertySets.iterator();
|
||||
boolean found = false;
|
||||
boolean multiple = false;
|
||||
BaseCompoundFile.PropertyStorage ps = null;
|
||||
while (i.hasNext()) {
|
||||
BaseCompoundFile.PropertyStorage ps2 = i.next();
|
||||
if (ps2.name.equalsIgnoreCase(name)) {
|
||||
multiple = (found == true);
|
||||
found = true;
|
||||
ps = ps2;
|
||||
}
|
||||
}
|
||||
if (multiple)
|
||||
logger.warn("found multiple copies of property set " + name);
|
||||
if (!found)
|
||||
throw new BiffException(BiffException.streamNotFound);
|
||||
return ps;
|
||||
}
|
||||
|
||||
private BaseCompoundFile.PropertyStorage getPropertyStorage(int index) {
|
||||
return this.propertySets.get(index);
|
||||
}
|
||||
|
||||
private byte[] getBigBlockStream(BaseCompoundFile.PropertyStorage ps) {
|
||||
int numBlocks = ps.size / 512;
|
||||
if (ps.size % 512 != 0)
|
||||
numBlocks++;
|
||||
byte[] streamData = new byte[numBlocks * 512];
|
||||
int block = ps.startBlock;
|
||||
int count = 0;
|
||||
int pos = 0;
|
||||
while (block != -2 && count < numBlocks) {
|
||||
pos = (block + 1) * 512;
|
||||
System.arraycopy(this.data, pos, streamData, count * 512, 512);
|
||||
count++;
|
||||
block = this.bigBlockChain[block];
|
||||
}
|
||||
if (block != -2 && count == numBlocks)
|
||||
logger.warn("Property storage size inconsistent with block chain.");
|
||||
return streamData;
|
||||
}
|
||||
|
||||
private byte[] getSmallBlockStream(BaseCompoundFile.PropertyStorage ps) throws BiffException {
|
||||
byte[] rootdata = readData(this.rootEntryPropertyStorage.startBlock);
|
||||
byte[] sbdata = new byte[0];
|
||||
int block = ps.startBlock;
|
||||
int pos = 0;
|
||||
while (block != -2) {
|
||||
byte[] olddata = sbdata;
|
||||
sbdata = new byte[olddata.length + 64];
|
||||
System.arraycopy(olddata, 0, sbdata, 0, olddata.length);
|
||||
pos = block * 64;
|
||||
System.arraycopy(rootdata, pos, sbdata, olddata.length, 64);
|
||||
block = this.smallBlockChain[block];
|
||||
if (block == -1) {
|
||||
logger.warn("Incorrect terminator for small block stream " + ps.name);
|
||||
block = -2;
|
||||
}
|
||||
}
|
||||
return sbdata;
|
||||
}
|
||||
|
||||
private byte[] readData(int bl) throws BiffException {
|
||||
int block = bl;
|
||||
int pos = 0;
|
||||
byte[] entry = new byte[0];
|
||||
while (block != -2) {
|
||||
byte[] oldEntry = entry;
|
||||
entry = new byte[oldEntry.length + 512];
|
||||
System.arraycopy(oldEntry, 0, entry, 0, oldEntry.length);
|
||||
pos = (block + 1) * 512;
|
||||
System.arraycopy(this.data, pos, entry, oldEntry.length, 512);
|
||||
if (this.bigBlockChain[block] == block)
|
||||
throw new BiffException(BiffException.corruptFileFormat);
|
||||
block = this.bigBlockChain[block];
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
public int getNumberOfPropertySets() {
|
||||
return this.propertySets.size();
|
||||
}
|
||||
|
||||
public BaseCompoundFile.PropertyStorage getPropertySet(int index) {
|
||||
return getPropertyStorage(index);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user