Search in sources :

Example 1 with RLEDecompressingInputStream

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();
        }
    }
}
Also used : RLEDecompressingInputStream(org.apache.poi.util.RLEDecompressingInputStream) Entry(org.apache.poi.poifs.filesystem.Entry) ZipEntry(java.util.zip.ZipEntry) DocumentNode(org.apache.poi.poifs.filesystem.DocumentNode) IOException(java.io.IOException) DocumentInputStream(org.apache.poi.poifs.filesystem.DocumentInputStream)

Example 2 with RLEDecompressingInputStream

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();
    }
}
Also used : RLEDecompressingInputStream(org.apache.poi.util.RLEDecompressingInputStream) ZipInputStream(java.util.zip.ZipInputStream) PushbackInputStream(java.io.PushbackInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) RLEDecompressingInputStream(org.apache.poi.util.RLEDecompressingInputStream) FileInputStream(java.io.FileInputStream) DocumentInputStream(org.apache.poi.poifs.filesystem.DocumentInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException)

Example 3 with RLEDecompressingInputStream

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();
    }
}
Also used : RLEDecompressingInputStream(org.apache.poi.util.RLEDecompressingInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) ZipInputStream(java.util.zip.ZipInputStream) PushbackInputStream(java.io.PushbackInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) RLEDecompressingInputStream(org.apache.poi.util.RLEDecompressingInputStream) FileInputStream(java.io.FileInputStream) DocumentInputStream(org.apache.poi.poifs.filesystem.DocumentInputStream) InputStream(java.io.InputStream)

Aggregations

DocumentInputStream (org.apache.poi.poifs.filesystem.DocumentInputStream)3 RLEDecompressingInputStream (org.apache.poi.util.RLEDecompressingInputStream)3 ByteArrayInputStream (java.io.ByteArrayInputStream)2 FileInputStream (java.io.FileInputStream)2 IOException (java.io.IOException)2 InputStream (java.io.InputStream)2 PushbackInputStream (java.io.PushbackInputStream)2 ZipInputStream (java.util.zip.ZipInputStream)2 ZipEntry (java.util.zip.ZipEntry)1 DocumentNode (org.apache.poi.poifs.filesystem.DocumentNode)1 Entry (org.apache.poi.poifs.filesystem.Entry)1