/** * 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 */ private static void ReadModule(RLEDecompressingInputStream in1, String streamName, ModuleMap modules) { int moduleOffset = in1.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(in1) here be correct? } else { // Decompress a previously found module and store the decompressed result into module.buf InputStream stream = new RLEDecompressingInputStream( new MemoryStream(module.buf, moduleOffset, module.buf.Length - moduleOffset) ); module.Read(stream); stream.Close(); } }
/** * 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) { foreach (Entry entry in macroDir) { if (!(entry is DocumentNode)) { continue; } String name = entry.Name; DocumentNode document = (DocumentNode)entry; DocumentInputStream dis = new DocumentInputStream(document); try { if ("dir".Equals(name, StringComparison.OrdinalIgnoreCase)) { // process DIR RLEDecompressingInputStream in1 = new RLEDecompressingInputStream(dis); String streamName = null; int recordId = 0; try { while (true) { recordId = in1.ReadShort(); if (EOF == recordId || VERSION_INDEPENDENT_TERMINATOR == recordId) { break; } int recordLength = in1.ReadInt(); switch (recordId) { case PROJECTVERSION: TrySkip(in1, 6); break; case PROJECTCODEPAGE: int codepage = in1.ReadShort(); ModuleMap.charset = Encoding.GetEncoding(codepage); //Charset.ForName("Cp" + codepage); break; case STREAMNAME: streamName = ReadString(in1, recordLength, ModuleMap.charset); break; case MODULEOFFSET: ReadModule(in1, streamName, modules); break; default: TrySkip(in1, recordLength); break; } } } catch (IOException e) { throw new IOException( "Error occurred while Reading macros at section id " + recordId + " (" + HexDump.ShortToHex(recordId) + ")", e); } finally { in1.Close(); } } else if (!name.StartsWith("__SRP", StringComparison.OrdinalIgnoreCase) && !name.StartsWith("_VBA_PROJECT", StringComparison.OrdinalIgnoreCase)) { // process module, skip __SRP and _VBA_PROJECT since these do not contain macros ReadModule(dis, name, modules); } } finally { dis.Close(); } } }