Example usage for org.apache.poi.util RLEDecompressingInputStream readInt

List of usage examples for org.apache.poi.util RLEDecompressingInputStream readInt

Introduction

In this page you can find the example usage for org.apache.poi.util RLEDecompressingInputStream readInt.

Prototype

public int readInt() throws IOException 

Source Link

Document

Convenience method for read a 4-bytes int in little endian encoding.

Usage

From source file:com.pnf.plugin.ole.parser.vba.VBAMacroExtractor.java

License:Apache License

/**
 * Extracts all macros from all modules of the provided input stream. The stream is assumed to
 * be in POIFS format (i.e. XLS file itself or vbaProject.bin from OOXML files)
 * /*from   ww w  .  j a  va 2s.  com*/
 * @param in
 * @return
 * @throws IOException
 */

@SuppressWarnings("resource")
public static Map<String, String> extractMacros(InputStream dirIn, Map<String, DocumentStream> streams) {
    try {
        class ModuleMap extends HashMap<String, VbaModule> {
            private static final long serialVersionUID = 1L;
            Charset charset = Charset.forName("Cp1252"); // default charset
        }

        final ModuleMap modules = new ModuleMap();

        // process DIR
        RLEDecompressingInputStream in = null;
        try {
            in = new RLEDecompressingInputStream(dirIn);
        } catch (ArrayIndexOutOfBoundsException e) {
            return null;
        }

        String streamName = null;
        while (true) {
            int id = in.readShort();
            if (id == -1 || id == 0x0010) {
                break; // EOF or TERMINATOR
            }
            int len = in.readInt();
            switch (id) {
            case 0x0009: // PROJECTVERSION
                in.skip(6);
                break;
            case 0x0003: // PROJECTCODEPAGE
                int codepage = in.readShort();
                modules.charset = Charset.forName("Cp" + codepage);
                break;
            case 0x001A: // STREAMNAME
                byte[] streamNameBuf = new byte[len];
                int count = in.read(streamNameBuf);
                streamName = new String(streamNameBuf, 0, count, modules.charset);
                break;
            case 0x0031: // MODULEOFFSET
                int moduleOffset = in.readInt();
                VbaModule module = modules.get(streamName);
                if (module != null) {
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    RLEDecompressingInputStream stream = new RLEDecompressingInputStream(
                            new ByteArrayInputStream(module.buf, moduleOffset,
                                    module.buf.length - moduleOffset));
                    IOUtils.copy(stream, out);
                    stream.close();
                    out.close();
                    module.buf = out.toByteArray();
                } else {
                    module = new VbaModule();
                    module.offset = moduleOffset;
                    modules.put(streamName, module);
                }
                break;
            default:
                in.skip(len);
                break;
            }
        }

        in.close();

        String attrib = "Attribu";
        byte[] temp = new byte[attrib.length()];

        Map<String, String> moduleSources = new HashMap<String, String>();

        for (String s : streams.keySet()) {
            ByteBuffer buff = streams.get(s).getBuffer();
            VbaModule module = modules.get(s);
            if (module != null) {
                // Read module using data we already collected
                read(module, buff);
            } else {
                // Otherwise, attempt to locate "Attribute" reserved word and use that as the basis for the module offset
                try {
                    int total = buff.remaining();
                    int pos = 0;
                    boolean found = false;
                    while (pos + temp.length < total && !found) {
                        buff.position(pos);
                        buff.get(temp);
                        found = attrib.equals(new String(temp));
                        if (!found)
                            pos++;
                        buff.rewind();
                    }

                    if (found) {
                        VbaModule m = new VbaModule();
                        m.offset = pos - 4; // for [01 00 b0 b7] bytes
                        modules.put(s, m);
                        read(m, buff);
                    }
                } catch (Throwable t) {
                    // Discard any errors since this is a last resort
                }
            }
        }

        for (Map.Entry<String, VbaModule> entry : modules.entrySet()) {
            VbaModule module = entry.getValue();
            if (module != null && module.buf != null && module.buf.length > 0) { // Skip empty modules
                moduleSources.put(entry.getKey(), new String(module.buf, modules.charset));
            }
        }

        return moduleSources;
    } catch (IOException e) {
        return null;
    }
}