use of org.apache.poi.util.RLEDecompressingInputStream in project poi by apache.
the class VBAMacroReader method readMacros.
/**
* Reads VBA Project modules from a VBA Project directory located at
* <tt>macroDir</tt> into <tt>modules</tt>.
*
* @since 3.15-beta2
*/
protected void readMacros(DirectoryNode macroDir, ModuleMap modules) throws IOException {
for (Entry entry : macroDir) {
if (!(entry instanceof DocumentNode)) {
continue;
}
String name = entry.getName();
DocumentNode document = (DocumentNode) entry;
DocumentInputStream dis = new DocumentInputStream(document);
try {
if ("dir".equalsIgnoreCase(name)) {
// process DIR
RLEDecompressingInputStream in = new RLEDecompressingInputStream(dis);
String streamName = null;
int recordId = 0;
try {
while (true) {
recordId = in.readShort();
if (EOF == recordId || VERSION_INDEPENDENT_TERMINATOR == recordId) {
break;
}
int recordLength = in.readInt();
switch(recordId) {
case PROJECTVERSION:
trySkip(in, 6);
break;
case PROJECTCODEPAGE:
int codepage = in.readShort();
modules.charset = Charset.forName(CodePageUtil.codepageToEncoding(codepage, true));
break;
case STREAMNAME:
streamName = readString(in, recordLength, modules.charset);
int reserved = in.readShort();
if (reserved != STREAMNAME_RESERVED) {
throw new IOException("Expected x0032 after stream name before Unicode stream name, but found: " + Integer.toHexString(reserved));
}
int unicodeNameRecordLength = in.readInt();
readUnicodeString(in, unicodeNameRecordLength);
// do something with this at some point
break;
case MODULEOFFSET:
readModule(in, streamName, modules);
break;
default:
trySkip(in, recordLength);
break;
}
}
} catch (final IOException e) {
throw new IOException("Error occurred while reading macros at section id " + recordId + " (" + HexDump.shortToHex(recordId) + ")", e);
} finally {
in.close();
}
} else if (!startsWithIgnoreCase(name, "__SRP") && !startsWithIgnoreCase(name, "_VBA_PROJECT")) {
// process module, skip __SRP and _VBA_PROJECT since these do not contain macros
readModule(dis, name, modules);
}
} finally {
dis.close();
}
}
}
use of org.apache.poi.util.RLEDecompressingInputStream in project poi by apache.
the class VBAMacroReader method readModule.
private static void readModule(DocumentInputStream dis, String name, ModuleMap modules) throws IOException {
Module module = modules.get(name);
// TODO Refactor this to fetch dir then do the rest
if (module == null) {
// no DIR stream with offsets yet, so store the compressed bytes for later
module = new Module();
modules.put(name, module);
module.read(dis);
} else if (module.buf == null) {
//if we haven't already read the bytes for the module keyed off this name...
if (module.offset == null) {
//This should not happen. bug 59858
throw new IOException("Module offset for '" + name + "' was never read.");
}
// we know the offset already, so decompress immediately on-the-fly
long skippedBytes = dis.skip(module.offset);
if (skippedBytes != module.offset) {
throw new IOException("tried to skip " + module.offset + " bytes, but actually skipped " + skippedBytes + " bytes");
}
InputStream stream = new RLEDecompressingInputStream(dis);
module.read(stream);
stream.close();
}
}
use of org.apache.poi.util.RLEDecompressingInputStream in project poi by apache.
the class VBAMacroReader method readModule.
/**
* reads module from DIR node in input stream and adds it to the modules map for decompression later
* on the second pass through this function, the module will be decompressed
*
* Side-effects: adds a new module to the module map or sets the buf field on the module
* to the decompressed stream contents (the VBA code for one module)
*
* @param in the run-length encoded input stream to read from
* @param streamName the stream name of the module
* @param modules a map to store the modules
* @throws IOException If reading data from the stream or from modules fails
*/
private static void readModule(RLEDecompressingInputStream in, String streamName, ModuleMap modules) throws IOException {
int moduleOffset = in.readInt();
Module module = modules.get(streamName);
if (module == null) {
// First time we've seen the module. Add it to the ModuleMap and decompress it later
module = new Module();
module.offset = moduleOffset;
modules.put(streamName, module);
// Would adding module.read(in) here be correct?
} else {
// Decompress a previously found module and store the decompressed result into module.buf
InputStream stream = new RLEDecompressingInputStream(new ByteArrayInputStream(module.buf, moduleOffset, module.buf.length - moduleOffset));
module.read(stream);
stream.close();
}
}
Aggregations