first commit

This commit is contained in:
2025-07-28 13:56:49 +05:30
commit e9eb805edb
3438 changed files with 520990 additions and 0 deletions

View 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);
}
}