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

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

Introduction

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

Prototype

@Override
    public int read(byte[] b) throws IOException 

Source Link

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   www .j  a v a  2s  . c o  m
 * @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;
    }
}