\r
package org.apache.poi.poifs.macros;\r
\r
+import static org.apache.poi.util.StringUtil.startsWithIgnoreCase;\r
+import static org.apache.poi.util.StringUtil.endsWithIgnoreCase;\r
+\r
import java.io.ByteArrayInputStream;\r
import java.io.ByteArrayOutputStream;\r
import java.io.Closeable;\r
* and returns them.\r
*/\r
public class VBAMacroReader implements Closeable {\r
- protected static final String VBA_PROJECT_OOXML = "xl/vbaProject.bin";\r
+ protected static final String VBA_PROJECT_OOXML = "vbaProject.bin";\r
protected static final String VBA_PROJECT_POIFS = "VBA";\r
\r
private NPOIFSFileSystem fs;\r
ZipInputStream zis = new ZipInputStream(zipFile);\r
ZipEntry zipEntry;\r
while ((zipEntry = zis.getNextEntry()) != null) {\r
- if (VBA_PROJECT_OOXML.equals(zipEntry.getName())) {\r
+ if (endsWithIgnoreCase(zipEntry.getName(), VBA_PROJECT_OOXML)) {\r
try {\r
// Make a NPOIFS from the contents, and close the stream\r
this.fs = new NPOIFSFileSystem(zis);\r
Charset charset = Charset.forName("Cp1252"); // default charset\r
}\r
\r
+ /**\r
+ * Recursively traverses directory structure rooted at <tt>dir</tt>.\r
+ * For each macro module that is found, the module's name and code are\r
+ * added to <tt>modules<tt>.\r
+ *\r
+ * @param dir\r
+ * @param modules\r
+ * @throws IOException\r
+ */\r
protected void findMacros(DirectoryNode dir, ModuleMap modules) throws IOException {\r
- if (VBA_PROJECT_POIFS.equals(dir.getName())) {\r
+ if (VBA_PROJECT_POIFS.equalsIgnoreCase(dir.getName())) {\r
// VBA project directory, process\r
readMacros(dir, modules);\r
} else {\r
}\r
}\r
}\r
+ \r
+ /**\r
+ * Read <tt>length</tt> bytes of MBCS (multi-byte character set) characters from the stream\r
+ *\r
+ * @param stream the inputstream to read from\r
+ * @param length number of bytes to read from stream\r
+ * @param charset the character set encoding of the bytes in the stream\r
+ * @return a java String in the supplied character set\r
+ * @throws IOException\r
+ */\r
+ private static String readString(InputStream stream, int length, Charset charset) throws IOException {\r
+ byte[] buffer = new byte[length];\r
+ int count = stream.read(buffer);\r
+ return new String(buffer, 0, count, charset);\r
+ }\r
+ \r
protected void readMacros(DirectoryNode macroDir, ModuleMap modules) throws IOException {\r
for (Entry entry : macroDir) {\r
if (! (entry instanceof DocumentNode)) { continue; }\r
String name = entry.getName();\r
DocumentNode document = (DocumentNode)entry;\r
DocumentInputStream dis = new DocumentInputStream(document);\r
- if ("dir".equals(name)) {\r
+ if ("dir".equalsIgnoreCase(name)) {\r
// process DIR\r
RLEDecompressingInputStream in = new RLEDecompressingInputStream(dis);\r
String streamName = null;\r
modules.charset = Charset.forName("Cp" + codepage);\r
break;\r
case 0x001A: // STREAMNAME\r
- byte[] streamNameBuf = new byte[len];\r
- int count = in.read(streamNameBuf);\r
- streamName = new String(streamNameBuf, 0, count, modules.charset);\r
+ streamName = readString(in, len, modules.charset);\r
break;\r
case 0x0031: // MODULEOFFSET\r
int moduleOffset = in.readInt();\r
}\r
}\r
in.close();\r
- } else if (!name.startsWith("__SRP") && !name.startsWith("_VBA_PROJECT")) {\r
+ } else if (!startsWithIgnoreCase(name, "__SRP")\r
+ && !startsWithIgnoreCase(name, "_VBA_PROJECT")) {\r
// process module, skip __SRP and _VBA_PROJECT since these do not contain macros\r
Module module = modules.get(name);\r
final InputStream in;\r
import static org.apache.poi.POITestCase.assertContains;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
import org.apache.poi.POIDataSamples;
-import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.StringUtil;
+import org.junit.Ignore;
import org.junit.Test;
public class TestVBAMacroReader {
- private final String testMacroContents;
- private final String testMacroNoSub;
- public TestVBAMacroReader() throws Exception {
- File macro = HSSFTestDataSamples.getSampleFile("SimpleMacro.vba");
- testMacroContents = new String(
- IOUtils.toByteArray(new FileInputStream(macro)),
- StringUtil.UTF8
- );
+
+ private static final Map<POIDataSamples, String> expectedMacroContents;
+ protected static String readVBA(POIDataSamples poiDataSamples) {
+ File macro = poiDataSamples.getFile("SimpleMacro.vba");
+ byte[] bytes;
+ try {
+ bytes = IOUtils.toByteArray(new FileInputStream(macro));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ String testMacroContents = new String(bytes, StringUtil.UTF8);
if (! testMacroContents.startsWith("Sub ")) {
throw new IllegalArgumentException("Not a macro");
}
- testMacroNoSub = testMacroContents.substring(testMacroContents.indexOf("()")+3);
+ String testMacroNoSub = testMacroContents.substring(testMacroContents.indexOf("()")+3);
+ return testMacroNoSub;
+ }
+ static {
+ final Map<POIDataSamples, String> _expectedMacroContents = new HashMap<POIDataSamples, String>();
+ final POIDataSamples[] dataSamples = {
+ POIDataSamples.getSpreadSheetInstance(),
+ POIDataSamples.getSlideShowInstance(),
+ POIDataSamples.getDocumentInstance(),
+ POIDataSamples.getDiagramInstance()
+ };
+ for (POIDataSamples sample : dataSamples) {
+ _expectedMacroContents.put(sample, readVBA(sample));
+ }
+ expectedMacroContents = Collections.unmodifiableMap(_expectedMacroContents);
}
+ //////////////////////////////// From Stream /////////////////////////////
@Test
public void HSSFfromStream() throws Exception {
fromStream(POIDataSamples.getSpreadSheetInstance(), "SimpleMacro.xls");
public void XSSFfromStream() throws Exception {
fromStream(POIDataSamples.getSpreadSheetInstance(), "SimpleMacro.xlsm");
}
+ @Ignore("Found 0 macros")
+ @Test
+ public void HSLFfromStream() throws Exception {
+ fromStream(POIDataSamples.getSlideShowInstance(), "SimpleMacro.ppt");
+ }
+ @Test
+ public void XSLFfromStream() throws Exception {
+ fromStream(POIDataSamples.getSlideShowInstance(), "SimpleMacro.pptm");
+ }
+ @Test
+ public void HWPFfromStream() throws Exception {
+ fromStream(POIDataSamples.getDocumentInstance(), "SimpleMacro.doc");
+ }
+ @Test
+ public void XWPFfromStream() throws Exception {
+ fromStream(POIDataSamples.getDocumentInstance(), "SimpleMacro.docm");
+ }
+ @Ignore("Found 0 macros")
+ @Test
+ public void HDGFfromStream() throws Exception {
+ fromStream(POIDataSamples.getDiagramInstance(), "SimpleMacro.vsd");
+ }
+ //////////////////////////////// From File /////////////////////////////
@Test
public void HSSFfromFile() throws Exception {
fromFile(POIDataSamples.getSpreadSheetInstance(), "SimpleMacro.xls");
public void XSSFfromFile() throws Exception {
fromFile(POIDataSamples.getSpreadSheetInstance(), "SimpleMacro.xlsm");
}
+ @Ignore("Found 0 macros")
+ @Test
+ public void HSLFfromFile() throws Exception {
+ fromFile(POIDataSamples.getSlideShowInstance(), "SimpleMacro.ppt");
+ }
+ @Test
+ public void XSLFfromFile() throws Exception {
+ fromFile(POIDataSamples.getSlideShowInstance(), "SimpleMacro.pptm");
+ }
+ @Test
+ public void HWPFfromFile() throws Exception {
+ fromFile(POIDataSamples.getDocumentInstance(), "SimpleMacro.doc");
+ }
+ @Test
+ public void XWPFfromFile() throws Exception {
+ fromFile(POIDataSamples.getDocumentInstance(), "SimpleMacro.docm");
+ }
+ @Ignore("Found 0 macros")
+ @Test
+ public void HDGFfromFile() throws Exception {
+ fromFile(POIDataSamples.getDiagramInstance(), "SimpleMacro.vsd");
+ }
+ //////////////////////////////// From NPOIFS /////////////////////////////
@Test
public void HSSFfromNPOIFS() throws Exception {
fromNPOIFS(POIDataSamples.getSpreadSheetInstance(), "SimpleMacro.xls");
}
+ @Ignore("Found 0 macros")
+ @Test
+ public void HSLFfromNPOIFS() throws Exception {
+ fromNPOIFS(POIDataSamples.getSlideShowInstance(), "SimpleMacro.ppt");
+ }
+ @Test
+ public void HWPFfromNPOIFS() throws Exception {
+ fromNPOIFS(POIDataSamples.getDocumentInstance(), "SimpleMacro.doc");
+ }
+ @Ignore("Found 0 macros")
+ @Test
+ public void HDGFfromNPOIFS() throws Exception {
+ fromNPOIFS(POIDataSamples.getDiagramInstance(), "SimpleMacro.vsd");
+ }
- protected void fromFile(POIDataSamples poiDataSamples, String filename) throws IOException {
- File f = poiDataSamples.getFile(filename);
+ protected void fromFile(POIDataSamples dataSamples, String filename) throws IOException {
+ File f = dataSamples.getFile(filename);
VBAMacroReader r = new VBAMacroReader(f);
try {
- assertMacroContents(r);
+ assertMacroContents(dataSamples, r);
} finally {
r.close();
}
}
- protected void fromStream(POIDataSamples poiDataSamples, String filename) throws IOException {
- InputStream fis = poiDataSamples.openResourceAsStream(filename);
+ protected void fromStream(POIDataSamples dataSamples, String filename) throws IOException {
+ InputStream fis = dataSamples.openResourceAsStream(filename);
try {
VBAMacroReader r = new VBAMacroReader(fis);
try {
- assertMacroContents(r);
+ assertMacroContents(dataSamples, r);
} finally {
r.close();
}
}
}
- protected void fromNPOIFS(POIDataSamples poiDataSamples, String filename) throws IOException {
- File f = poiDataSamples.getFile(filename);
+ protected void fromNPOIFS(POIDataSamples dataSamples, String filename) throws IOException {
+ File f = dataSamples.getFile(filename);
NPOIFSFileSystem fs = new NPOIFSFileSystem(f);
try {
VBAMacroReader r = new VBAMacroReader(fs);
try {
- assertMacroContents(r);
+ assertMacroContents(dataSamples, r);
} finally {
r.close();
}
}
}
- protected void assertMacroContents(VBAMacroReader r) throws IOException {
+ protected void assertMacroContents(POIDataSamples samples, VBAMacroReader r) throws IOException {
+ assertNotNull(r);
Map<String,String> contents = r.readMacros();
-
- assertFalse(contents.isEmpty());
+ assertNotNull(contents);
+ assertFalse("Found 0 macros", contents.isEmpty());
+ /*
assertEquals(5, contents.size());
// Check the ones without scripts
assertContains(content, "Attribute VB_GlobalNameSpace = False");
assertContains(content, "Attribute VB_Exposed = True");
}
+ */
// Check the script one
+ assertContains(contents, "Module1");
String content = contents.get("Module1");
+ assertNotNull(content);
assertContains(content, "Attribute VB_Name = \"Module1\"");
- assertContains(content, "Attribute TestMacro.VB_Description = \"This is a test macro\"");
+ //assertContains(content, "Attribute TestMacro.VB_Description = \"This is a test macro\"");
// And the macro itself
+ String testMacroNoSub = expectedMacroContents.get(samples);
assertContains(content, testMacroNoSub);
}
}