mirror of https://github.com/apache/poi.git
#63955 - HMEFContentsExtractor fails to extract content from winmail.dat
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1870692 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
713a69afdb
commit
2eee474063
|
@ -26,8 +26,8 @@ import java.util.Map;
|
||||||
* http://msdn.microsoft.com/en-us/library/microsoft.exchange.data.contenttypes.tnef.tnefpropertytype%28v=EXCHG.140%29.aspx
|
* http://msdn.microsoft.com/en-us/library/microsoft.exchange.data.contenttypes.tnef.tnefpropertytype%28v=EXCHG.140%29.aspx
|
||||||
*/
|
*/
|
||||||
public final class Types {
|
public final class Types {
|
||||||
private static Map<Integer, MAPIType> builtInTypes = new HashMap<>();
|
private static final Map<Integer, MAPIType> builtInTypes = new HashMap<>();
|
||||||
private static Map<Integer, MAPIType> customTypes = new HashMap<>();
|
private static final Map<Integer, MAPIType> customTypes = new HashMap<>();
|
||||||
|
|
||||||
/** Unspecified */
|
/** Unspecified */
|
||||||
public static final MAPIType UNSPECIFIED = new MAPIType(0x0000,
|
public static final MAPIType UNSPECIFIED = new MAPIType(0x0000,
|
||||||
|
@ -119,7 +119,7 @@ public final class Types {
|
||||||
* Is this type a fixed-length type, or a variable-length one?
|
* Is this type a fixed-length type, or a variable-length one?
|
||||||
*/
|
*/
|
||||||
public boolean isFixedLength() {
|
public boolean isFixedLength() {
|
||||||
return (length != -1) && (length <= 8);
|
return ((length != -1) && (length <= 8)) || (id == Types.CLS_ID.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
|
@ -132,8 +132,7 @@ public final class Types {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return id + " / 0x" + asFileEnding() + " - " + name + " @ "
|
return id + " / 0x" + asFileEnding() + " - " + name + " @ " + length;
|
||||||
+ length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
/* ====================================================================
|
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
contributor license agreements. See the NOTICE file distributed with
|
|
||||||
this work for additional information regarding copyright ownership.
|
|
||||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
(the "License"); you may not use this file except in compliance with
|
|
||||||
the License. You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
==================================================================== */
|
|
||||||
|
|
||||||
package org.apache.poi.hmef;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
|
||||||
import org.apache.poi.util.IOUtils;
|
|
||||||
|
|
||||||
public abstract class HMEFTest extends TestCase {
|
|
||||||
protected static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
|
|
||||||
|
|
||||||
protected void assertContents(String filename, Attachment attachment)
|
|
||||||
throws IOException {
|
|
||||||
assertEquals(filename, attachment.getLongFilename());
|
|
||||||
assertContents(filename, attachment.getContents());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertContents(String filename, byte[] actual)
|
|
||||||
throws IOException {
|
|
||||||
try (InputStream stream = _samples.openResourceAsStream("quick-contents/" + filename)) {
|
|
||||||
byte[] expected = IOUtils.toByteArray(stream);
|
|
||||||
|
|
||||||
assertEquals(expected.length, actual.length);
|
|
||||||
for (int i = 0; i < expected.length; i++) {
|
|
||||||
assertEquals("Byte " + i + " wrong", expected[i], actual[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,101 +17,117 @@
|
||||||
|
|
||||||
package org.apache.poi.hmef;
|
package org.apache.poi.hmef;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.util.LocaleUtil;
|
import org.apache.poi.util.LocaleUtil;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public final class TestAttachments extends HMEFTest {
|
public final class TestAttachments {
|
||||||
private HMEFMessage quick;
|
protected static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
|
|
||||||
quick = new HMEFMessage(
|
private HMEFMessage quick;
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
@Before
|
||||||
* Check the file is as we expect
|
public void setUp() throws Exception {
|
||||||
*/
|
quick = new HMEFMessage(
|
||||||
public void testCounts() throws Exception {
|
_samples.openResourceAsStream("quick-winmail.dat")
|
||||||
// Should have 5 attachments
|
);
|
||||||
assertEquals(5, quick.getAttachments().size());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check some basic bits about the attachments
|
* Check the file is as we expect
|
||||||
*/
|
*/
|
||||||
public void testBasicAttachments() throws Exception {
|
@Test
|
||||||
List<Attachment> attachments = quick.getAttachments();
|
public void testCounts() throws Exception {
|
||||||
|
// Should have 5 attachments
|
||||||
|
assertEquals(5, quick.getAttachments().size());
|
||||||
|
}
|
||||||
|
|
||||||
// Word first
|
/**
|
||||||
assertEquals("quick.doc", attachments.get(0).getFilename());
|
* Check some basic bits about the attachments
|
||||||
assertEquals("quick.doc", attachments.get(0).getLongFilename());
|
*/
|
||||||
assertEquals(".doc", attachments.get(0).getExtension());
|
@Test
|
||||||
|
public void testBasicAttachments() throws Exception {
|
||||||
|
List<Attachment> attachments = quick.getAttachments();
|
||||||
|
|
||||||
// Then HTML
|
// Word first
|
||||||
assertEquals("QUICK~1.HTM", attachments.get(1).getFilename());
|
assertEquals("quick.doc", attachments.get(0).getFilename());
|
||||||
assertEquals("quick.html", attachments.get(1).getLongFilename());
|
assertEquals("quick.doc", attachments.get(0).getLongFilename());
|
||||||
assertEquals(".html", attachments.get(1).getExtension());
|
assertEquals(".doc", attachments.get(0).getExtension());
|
||||||
|
|
||||||
// Then PDF
|
// Then HTML
|
||||||
assertEquals("quick.pdf", attachments.get(2).getFilename());
|
assertEquals("QUICK~1.HTM", attachments.get(1).getFilename());
|
||||||
assertEquals("quick.pdf", attachments.get(2).getLongFilename());
|
assertEquals("quick.html", attachments.get(1).getLongFilename());
|
||||||
assertEquals(".pdf", attachments.get(2).getExtension());
|
assertEquals(".html", attachments.get(1).getExtension());
|
||||||
|
|
||||||
// Then Text
|
// Then PDF
|
||||||
assertEquals("quick.txt", attachments.get(3).getFilename());
|
assertEquals("quick.pdf", attachments.get(2).getFilename());
|
||||||
assertEquals("quick.txt", attachments.get(3).getLongFilename());
|
assertEquals("quick.pdf", attachments.get(2).getLongFilename());
|
||||||
assertEquals(".txt", attachments.get(3).getExtension());
|
assertEquals(".pdf", attachments.get(2).getExtension());
|
||||||
|
|
||||||
// And finally XML
|
// Then Text
|
||||||
assertEquals("quick.xml", attachments.get(4).getFilename());
|
assertEquals("quick.txt", attachments.get(3).getFilename());
|
||||||
assertEquals("quick.xml", attachments.get(4).getLongFilename());
|
assertEquals("quick.txt", attachments.get(3).getLongFilename());
|
||||||
assertEquals(".xml", attachments.get(4).getExtension());
|
assertEquals(".txt", attachments.get(3).getExtension());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// And finally XML
|
||||||
* Query the attachments in detail, and check we see
|
assertEquals("quick.xml", attachments.get(4).getFilename());
|
||||||
* the right values for key things
|
assertEquals("quick.xml", attachments.get(4).getLongFilename());
|
||||||
*/
|
assertEquals(".xml", attachments.get(4).getExtension());
|
||||||
public void testAttachmentDetails() throws Exception {
|
}
|
||||||
List<Attachment> attachments = quick.getAttachments();
|
|
||||||
|
|
||||||
// Pick a predictable date format + timezone
|
/**
|
||||||
DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss", Locale.UK);
|
* Query the attachments in detail, and check we see
|
||||||
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
* the right values for key things
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testAttachmentDetails() throws Exception {
|
||||||
|
List<Attachment> attachments = quick.getAttachments();
|
||||||
|
|
||||||
// They should all have the same date on them
|
// Pick a predictable date format + timezone
|
||||||
assertEquals("28-Apr-2010 12:40:56", fmt.format( attachments.get(0).getModifiedDate()));
|
DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss", Locale.UK);
|
||||||
assertEquals("28-Apr-2010 12:40:56", fmt.format( attachments.get(1).getModifiedDate()));
|
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
||||||
assertEquals("28-Apr-2010 12:40:56", fmt.format( attachments.get(2).getModifiedDate()));
|
|
||||||
assertEquals("28-Apr-2010 12:40:56", fmt.format( attachments.get(3).getModifiedDate()));
|
|
||||||
assertEquals("28-Apr-2010 12:40:56", fmt.format( attachments.get(4).getModifiedDate()));
|
|
||||||
|
|
||||||
// They should all have a 3512 byte metafile rendered version
|
// They should all have the same date on them
|
||||||
assertEquals(3512, attachments.get(0).getRenderedMetaFile().length);
|
assertEquals("28-Apr-2010 12:40:56", fmt.format(attachments.get(0).getModifiedDate()));
|
||||||
assertEquals(3512, attachments.get(1).getRenderedMetaFile().length);
|
assertEquals("28-Apr-2010 12:40:56", fmt.format(attachments.get(1).getModifiedDate()));
|
||||||
assertEquals(3512, attachments.get(2).getRenderedMetaFile().length);
|
assertEquals("28-Apr-2010 12:40:56", fmt.format(attachments.get(2).getModifiedDate()));
|
||||||
assertEquals(3512, attachments.get(3).getRenderedMetaFile().length);
|
assertEquals("28-Apr-2010 12:40:56", fmt.format(attachments.get(3).getModifiedDate()));
|
||||||
assertEquals(3512, attachments.get(4).getRenderedMetaFile().length);
|
assertEquals("28-Apr-2010 12:40:56", fmt.format(attachments.get(4).getModifiedDate()));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// They should all have a 3512 byte metafile rendered version
|
||||||
* Ensure the attachment contents come back as they should do
|
assertEquals(3512, attachments.get(0).getRenderedMetaFile().length);
|
||||||
*/
|
assertEquals(3512, attachments.get(1).getRenderedMetaFile().length);
|
||||||
public void testAttachmentContents() throws Exception {
|
assertEquals(3512, attachments.get(2).getRenderedMetaFile().length);
|
||||||
List<Attachment> attachments = quick.getAttachments();
|
assertEquals(3512, attachments.get(3).getRenderedMetaFile().length);
|
||||||
|
assertEquals(3512, attachments.get(4).getRenderedMetaFile().length);
|
||||||
|
}
|
||||||
|
|
||||||
assertContents("quick.doc", attachments.get(0));
|
/**
|
||||||
assertContents("quick.html", attachments.get(1));
|
* Ensure the attachment contents come back as they should do
|
||||||
assertContents("quick.pdf", attachments.get(2));
|
*/
|
||||||
assertContents("quick.txt", attachments.get(3));
|
@Test
|
||||||
assertContents("quick.xml", attachments.get(4));
|
public void testAttachmentContents() throws Exception {
|
||||||
}
|
List<Attachment> attachments = quick.getAttachments();
|
||||||
|
|
||||||
|
assertContents("quick.doc", attachments.get(0));
|
||||||
|
assertContents("quick.html", attachments.get(1));
|
||||||
|
assertContents("quick.pdf", attachments.get(2));
|
||||||
|
assertContents("quick.txt", attachments.get(3));
|
||||||
|
assertContents("quick.xml", attachments.get(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assertContents(String filename, Attachment attachment) throws IOException {
|
||||||
|
assertEquals(filename, attachment.getLongFilename());
|
||||||
|
TestHMEFMessage.assertContents(filename, attachment.getContents());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,13 @@
|
||||||
|
|
||||||
package org.apache.poi.hmef;
|
package org.apache.poi.hmef;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.hmef.attribute.MAPIAttribute;
|
import org.apache.poi.hmef.attribute.MAPIAttribute;
|
||||||
import org.apache.poi.hmef.attribute.MAPIRtfAttribute;
|
import org.apache.poi.hmef.attribute.MAPIRtfAttribute;
|
||||||
|
@ -29,8 +31,9 @@ import org.apache.poi.hsmf.datatypes.MAPIProperty;
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.StringUtil;
|
import org.apache.poi.util.StringUtil;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public final class TestCompressedRTF extends TestCase {
|
public final class TestCompressedRTF {
|
||||||
private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
|
private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
|
||||||
|
|
||||||
private static final String block1 = "{\\rtf1\\adeflang102";
|
private static final String block1 = "{\\rtf1\\adeflang102";
|
||||||
|
@ -38,157 +41,163 @@ public final class TestCompressedRTF extends TestCase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that things are as we expected. If this fails,
|
* Check that things are as we expected. If this fails,
|
||||||
* then decoding has no hope...
|
* then decoding has no hope...
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testQuickBasics() throws Exception {
|
public void testQuickBasics() throws Exception {
|
||||||
HMEFMessage msg = new HMEFMessage(
|
HMEFMessage msg;
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
try (InputStream is = _samples.openResourceAsStream("quick-winmail.dat")) {
|
||||||
);
|
msg = new HMEFMessage(is);
|
||||||
|
}
|
||||||
|
|
||||||
MAPIAttribute rtfAttr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
MAPIAttribute rtfAttr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
||||||
assertNotNull(rtfAttr);
|
assertNotNull(rtfAttr);
|
||||||
assertTrue(rtfAttr instanceof MAPIRtfAttribute);
|
assertTrue(rtfAttr instanceof MAPIRtfAttribute);
|
||||||
|
|
||||||
// Check the start of the compressed version
|
// Check the start of the compressed version
|
||||||
byte[] data = ((MAPIRtfAttribute)rtfAttr).getRawData();
|
byte[] data = ((MAPIRtfAttribute) rtfAttr).getRawData();
|
||||||
assertEquals(5907, data.length);
|
assertEquals(5907, data.length);
|
||||||
|
|
||||||
// First 16 bytes is header stuff
|
// First 16 bytes is header stuff
|
||||||
// Check it has the length + compressed marker
|
// Check it has the length + compressed marker
|
||||||
assertEquals(5907-4, LittleEndian.getShort(data));
|
assertEquals(5907 - 4, LittleEndian.getShort(data));
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"LZFu",
|
"LZFu",
|
||||||
StringUtil.getFromCompressedUnicode(data, 8, 4)
|
StringUtil.getFromCompressedUnicode(data, 8, 4)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Now Look at the code
|
// Now Look at the code
|
||||||
assertEquals((byte)0x07, data[16+0]); // Flag: cccUUUUU
|
assertEquals((byte) 0x07, data[16 + 0]); // Flag: cccUUUUU
|
||||||
assertEquals((byte)0x00, data[16+1]); // c1a: offset 0 / 0x000
|
assertEquals((byte) 0x00, data[16 + 1]); // c1a: offset 0 / 0x000
|
||||||
assertEquals((byte)0x06, data[16+2]); // c1b: length 6+2 -> {\rtf1\a
|
assertEquals((byte) 0x06, data[16 + 2]); // c1b: length 6+2 -> {\rtf1\a
|
||||||
assertEquals((byte)0x01, data[16+3]); // c2a: offset 16 / 0x010
|
assertEquals((byte) 0x01, data[16 + 3]); // c2a: offset 16 / 0x010
|
||||||
assertEquals((byte)0x01, data[16+4]); // c2b: length 1+2 -> def
|
assertEquals((byte) 0x01, data[16 + 4]); // c2b: length 1+2 -> def
|
||||||
assertEquals((byte)0x0b, data[16+5]); // c3a: offset 182 / 0xb6
|
assertEquals((byte) 0x0b, data[16 + 5]); // c3a: offset 182 / 0xb6
|
||||||
assertEquals((byte)0x60, data[16+6]); // c3b: length 0+2 -> la
|
assertEquals((byte) 0x60, data[16 + 6]); // c3b: length 0+2 -> la
|
||||||
assertEquals((byte)0x6e, data[16+7]); // n
|
assertEquals((byte) 0x6e, data[16 + 7]); // n
|
||||||
assertEquals((byte)0x67, data[16+8]); // g
|
assertEquals((byte) 0x67, data[16 + 8]); // g
|
||||||
assertEquals((byte)0x31, data[16+9]); // 1
|
assertEquals((byte) 0x31, data[16 + 9]); // 1
|
||||||
assertEquals((byte)0x30, data[16+10]); // 0
|
assertEquals((byte) 0x30, data[16 + 10]); // 0
|
||||||
assertEquals((byte)0x32, data[16+11]); // 2
|
assertEquals((byte) 0x32, data[16 + 11]); // 2
|
||||||
|
|
||||||
assertEquals((byte)0x66, data[16+12]); // Flag: UccUUccU
|
assertEquals((byte) 0x66, data[16 + 12]); // Flag: UccUUccU
|
||||||
assertEquals((byte)0x35, data[16+13]); // 5
|
assertEquals((byte) 0x35, data[16 + 13]); // 5
|
||||||
assertEquals((byte)0x00, data[16+14]); // c2a: offset 6 / 0x006
|
assertEquals((byte) 0x00, data[16 + 14]); // c2a: offset 6 / 0x006
|
||||||
assertEquals((byte)0x64, data[16+15]); // c2b: length 4+2 -> \ansi\a
|
assertEquals((byte) 0x64, data[16 + 15]); // c2b: length 4+2 -> \ansi\a
|
||||||
assertEquals((byte)0x00, data[16+16]); // c3a: offset 7 / 0x007
|
assertEquals((byte) 0x00, data[16 + 16]); // c3a: offset 7 / 0x007
|
||||||
assertEquals((byte)0x72, data[16+17]); // c3b: length 2+2 -> nsi
|
assertEquals((byte) 0x72, data[16 + 17]); // c3b: length 2+2 -> nsi
|
||||||
assertEquals((byte)0x63, data[16+18]); // c
|
assertEquals((byte) 0x63, data[16 + 18]); // c
|
||||||
assertEquals((byte)0x70, data[16+19]); // p
|
assertEquals((byte) 0x70, data[16 + 19]); // p
|
||||||
assertEquals((byte)0x0d, data[16+20]); // c6a: offset 221 / 0x0dd
|
assertEquals((byte) 0x0d, data[16 + 20]); // c6a: offset 221 / 0x0dd
|
||||||
assertEquals((byte)0xd0, data[16+21]); // c6b: length 0+2 -> g1
|
assertEquals((byte) 0xd0, data[16 + 21]); // c6b: length 0+2 -> g1
|
||||||
assertEquals((byte)0x0e, data[16+22]); // c7a: offset 224 / 0x0e0
|
assertEquals((byte) 0x0e, data[16 + 22]); // c7a: offset 224 / 0x0e0
|
||||||
assertEquals((byte)0x00, data[16+23]); // c7b: length 0+2 -> 25
|
assertEquals((byte) 0x00, data[16 + 23]); // c7b: length 0+2 -> 25
|
||||||
assertEquals((byte)0x32, data[16+24]); // 2
|
assertEquals((byte) 0x32, data[16 + 24]); // 2
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that we can decode the first 8 codes
|
* Check that we can decode the first 8 codes
|
||||||
* (1 flag byte + 8 codes)
|
* (1 flag byte + 8 codes)
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testFirstBlock() throws Exception {
|
public void testFirstBlock() throws Exception {
|
||||||
HMEFMessage msg = new HMEFMessage(
|
HMEFMessage msg;
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
try (InputStream is = _samples.openResourceAsStream("quick-winmail.dat")) {
|
||||||
);
|
msg = new HMEFMessage(is);
|
||||||
|
}
|
||||||
|
|
||||||
MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
||||||
assertNotNull(attr);
|
assertNotNull(attr);
|
||||||
MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute)attr;
|
MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute) attr;
|
||||||
|
|
||||||
// Truncate to header + flag + data for flag
|
// Truncate to header + flag + data for flag
|
||||||
byte[] data = new byte[16+12];
|
byte[] data = new byte[16 + 12];
|
||||||
System.arraycopy(rtfAttr.getRawData(), 0, data, 0, data.length);
|
System.arraycopy(rtfAttr.getRawData(), 0, data, 0, data.length);
|
||||||
|
|
||||||
// Decompress it
|
// Decompress it
|
||||||
CompressedRTF comp = new CompressedRTF();
|
CompressedRTF comp = new CompressedRTF();
|
||||||
byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
|
byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
|
||||||
String decompStr = new String(decomp, "ASCII");
|
String decompStr = new String(decomp, "ASCII");
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
assertEquals(block1.length(), decomp.length);
|
assertEquals(block1.length(), decomp.length);
|
||||||
assertEquals(block1, decompStr);
|
assertEquals(block1, decompStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that we can decode the first 16 codes
|
* Check that we can decode the first 16 codes
|
||||||
* (flag + 8 codes, flag + 8 codes)
|
* (flag + 8 codes, flag + 8 codes)
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testFirstTwoBlocks() throws Exception {
|
public void testFirstTwoBlocks() throws Exception {
|
||||||
HMEFMessage msg = new HMEFMessage(
|
HMEFMessage msg;
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
try (InputStream is = _samples.openResourceAsStream("quick-winmail.dat")) {
|
||||||
);
|
msg = new HMEFMessage(is);
|
||||||
|
}
|
||||||
|
|
||||||
MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
||||||
assertNotNull(attr);
|
assertNotNull(attr);
|
||||||
MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute)attr;
|
MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute) attr;
|
||||||
|
|
||||||
// Truncate to header + flag + data for flag + flag + data
|
// Truncate to header + flag + data for flag + flag + data
|
||||||
byte[] data = new byte[16+12+13];
|
byte[] data = new byte[16 + 12 + 13];
|
||||||
System.arraycopy(rtfAttr.getRawData(), 0, data, 0, data.length);
|
System.arraycopy(rtfAttr.getRawData(), 0, data, 0, data.length);
|
||||||
|
|
||||||
// Decompress it
|
// Decompress it
|
||||||
CompressedRTF comp = new CompressedRTF();
|
CompressedRTF comp = new CompressedRTF();
|
||||||
byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
|
byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
|
||||||
String decompStr = new String(decomp, "ASCII");
|
String decompStr = new String(decomp, "ASCII");
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
assertEquals(block2.length(), decomp.length);
|
assertEquals(block2.length(), decomp.length);
|
||||||
assertEquals(block2, decompStr);
|
assertEquals(block2, decompStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that we can correctly decode the whole file
|
* Check that we can correctly decode the whole file
|
||||||
* TODO Fix what looks like a padding issue
|
* TODO Fix what looks like a padding issue
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testFull() throws Exception {
|
public void testFull() throws Exception {
|
||||||
HMEFMessage msg = new HMEFMessage(
|
final HMEFMessage msg;
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
try (InputStream is = _samples.openResourceAsStream("quick-winmail.dat")) {
|
||||||
);
|
msg = new HMEFMessage(is);
|
||||||
|
}
|
||||||
|
|
||||||
MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
||||||
assertNotNull(attr);
|
assertNotNull(attr);
|
||||||
MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute)attr;
|
MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute) attr;
|
||||||
|
|
||||||
InputStream stream = _samples.openResourceAsStream("quick-contents/message.rtf");
|
final byte[] expected;
|
||||||
try {
|
try (InputStream stream = _samples.openResourceAsStream("quick-contents/message.rtf")) {
|
||||||
byte[] expected = IOUtils.toByteArray(stream);
|
expected = IOUtils.toByteArray(stream);
|
||||||
|
}
|
||||||
|
|
||||||
CompressedRTF comp = new CompressedRTF();
|
CompressedRTF comp = new CompressedRTF();
|
||||||
byte[] data = rtfAttr.getRawData();
|
byte[] data = rtfAttr.getRawData();
|
||||||
byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
|
byte[] decomp = comp.decompress(new ByteArrayInputStream(data));
|
||||||
|
|
||||||
// Check the length was as expected
|
// Check the length was as expected
|
||||||
assertEquals(data.length, comp.getCompressedSize() + 16);
|
assertEquals(data.length, comp.getCompressedSize() + 16);
|
||||||
assertEquals(expected.length, comp.getDeCompressedSize());
|
assertEquals(expected.length, comp.getDeCompressedSize());
|
||||||
|
|
||||||
// Will have been padded though
|
// Will have been padded though
|
||||||
assertEquals(expected.length+2, decomp.length);
|
assertEquals(expected.length + 2, decomp.length);
|
||||||
byte[] tmp = new byte[expected.length];
|
byte[] tmp = new byte[expected.length];
|
||||||
System.arraycopy(decomp, 0, tmp, 0, tmp.length);
|
System.arraycopy(decomp, 0, tmp, 0, tmp.length);
|
||||||
decomp = tmp;
|
decomp = tmp;
|
||||||
|
|
||||||
// By byte
|
// By byte
|
||||||
assertEquals(expected.length, decomp.length);
|
assertEquals(expected.length, decomp.length);
|
||||||
for(int i=0; i<expected.length; i++) {
|
for (int i = 0; i < expected.length; i++) {
|
||||||
assertEquals(expected[i], decomp[i]);
|
assertEquals(expected[i], decomp[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// By String
|
// By String
|
||||||
String expString = new String(expected, "ASCII");
|
String expString = new String(expected, "ASCII");
|
||||||
String decompStr = rtfAttr.getDataString();
|
String decompStr = rtfAttr.getDataString();
|
||||||
assertEquals(expString.length(), decompStr.length());
|
assertEquals(expString.length(), decompStr.length());
|
||||||
assertEquals(expString, decompStr);
|
assertEquals(expString, decompStr);
|
||||||
} finally {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,217 +17,251 @@
|
||||||
|
|
||||||
package org.apache.poi.hmef;
|
package org.apache.poi.hmef;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.hmef.attribute.MAPIAttribute;
|
import org.apache.poi.hmef.attribute.MAPIAttribute;
|
||||||
import org.apache.poi.hmef.attribute.MAPIRtfAttribute;
|
import org.apache.poi.hmef.attribute.MAPIRtfAttribute;
|
||||||
import org.apache.poi.hmef.attribute.MAPIStringAttribute;
|
import org.apache.poi.hmef.attribute.MAPIStringAttribute;
|
||||||
import org.apache.poi.hmef.attribute.TNEFProperty;
|
import org.apache.poi.hmef.attribute.TNEFProperty;
|
||||||
import org.apache.poi.hsmf.datatypes.MAPIProperty;
|
import org.apache.poi.hsmf.datatypes.MAPIProperty;
|
||||||
import org.apache.poi.hsmf.datatypes.Types;
|
import org.apache.poi.hsmf.datatypes.Types;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public final class TestHMEFMessage extends HMEFTest {
|
public final class TestHMEFMessage {
|
||||||
public void testOpen() throws Exception {
|
protected static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
|
||||||
HMEFMessage msg = new HMEFMessage(
|
|
||||||
|
@Test
|
||||||
|
public void testOpen() throws Exception {
|
||||||
|
HMEFMessage msg = new HMEFMessage(
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
_samples.openResourceAsStream("quick-winmail.dat")
|
||||||
);
|
);
|
||||||
|
|
||||||
assertNotNull(msg);
|
assertNotNull(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCounts() throws Exception {
|
@Test
|
||||||
HMEFMessage msg = new HMEFMessage(
|
public void testCounts() throws Exception {
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
HMEFMessage msg = new HMEFMessage(
|
||||||
);
|
_samples.openResourceAsStream("quick-winmail.dat")
|
||||||
|
);
|
||||||
|
|
||||||
// Should have 4 attributes on the message
|
// Should have 4 attributes on the message
|
||||||
assertEquals(4, msg.getMessageAttributes().size());
|
assertEquals(4, msg.getMessageAttributes().size());
|
||||||
|
|
||||||
// And should have 54 MAPI attributes on it
|
// And should have 54 MAPI attributes on it
|
||||||
assertEquals(54, msg.getMessageMAPIAttributes().size());
|
assertEquals(54, msg.getMessageMAPIAttributes().size());
|
||||||
|
|
||||||
|
|
||||||
// Should have 5 attachments
|
// Should have 5 attachments
|
||||||
assertEquals(5, msg.getAttachments().size());
|
assertEquals(5, msg.getAttachments().size());
|
||||||
|
|
||||||
// Each attachment should have 6 normal attributes, and
|
// Each attachment should have 6 normal attributes, and
|
||||||
// 20 or so MAPI ones
|
// 20 or so MAPI ones
|
||||||
for(Attachment attach : msg.getAttachments()) {
|
for (Attachment attach : msg.getAttachments()) {
|
||||||
int attrCount = attach.getAttributes().size();
|
int attrCount = attach.getAttributes().size();
|
||||||
int mapiAttrCount = attach.getMAPIAttributes().size();
|
int mapiAttrCount = attach.getMAPIAttributes().size();
|
||||||
|
|
||||||
assertEquals(6, attrCount);
|
assertEquals(6, attrCount);
|
||||||
assertTrue("Should be 20-25 mapi attributes, found " + mapiAttrCount, mapiAttrCount >= 20);
|
assertTrue("Should be 20-25 mapi attributes, found " + mapiAttrCount, mapiAttrCount >= 20);
|
||||||
assertTrue("Should be 20-25 mapi attributes, found " + mapiAttrCount, mapiAttrCount <= 25);
|
assertTrue("Should be 20-25 mapi attributes, found " + mapiAttrCount, mapiAttrCount <= 25);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBasicMessageAttributes() throws Exception {
|
@Test
|
||||||
HMEFMessage msg = new HMEFMessage(
|
public void testBasicMessageAttributes() throws Exception {
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
HMEFMessage msg = new HMEFMessage(
|
||||||
);
|
_samples.openResourceAsStream("quick-winmail.dat")
|
||||||
|
);
|
||||||
|
|
||||||
// Should have version, codepage, class and MAPI
|
// Should have version, codepage, class and MAPI
|
||||||
assertEquals(4, msg.getMessageAttributes().size());
|
assertEquals(4, msg.getMessageAttributes().size());
|
||||||
assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_TNEFVERSION));
|
assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_TNEFVERSION));
|
||||||
assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_OEMCODEPAGE));
|
assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_OEMCODEPAGE));
|
||||||
assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS));
|
assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS));
|
||||||
assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_MAPIPROPERTIES));
|
assertNotNull(msg.getMessageAttribute(TNEFProperty.ID_MAPIPROPERTIES));
|
||||||
|
|
||||||
// Check the order
|
// Check the order
|
||||||
assertEquals(TNEFProperty.ID_TNEFVERSION, msg.getMessageAttributes().get(0).getProperty());
|
assertEquals(TNEFProperty.ID_TNEFVERSION, msg.getMessageAttributes().get(0).getProperty());
|
||||||
assertEquals(TNEFProperty.ID_OEMCODEPAGE, msg.getMessageAttributes().get(1).getProperty());
|
assertEquals(TNEFProperty.ID_OEMCODEPAGE, msg.getMessageAttributes().get(1).getProperty());
|
||||||
assertEquals(TNEFProperty.ID_MESSAGECLASS, msg.getMessageAttributes().get(2).getProperty());
|
assertEquals(TNEFProperty.ID_MESSAGECLASS, msg.getMessageAttributes().get(2).getProperty());
|
||||||
assertEquals(TNEFProperty.ID_MAPIPROPERTIES, msg.getMessageAttributes().get(3).getProperty());
|
assertEquals(TNEFProperty.ID_MAPIPROPERTIES, msg.getMessageAttributes().get(3).getProperty());
|
||||||
|
|
||||||
// Check some that aren't there
|
// Check some that aren't there
|
||||||
assertNull(msg.getMessageAttribute(TNEFProperty.ID_AIDOWNER));
|
assertNull(msg.getMessageAttribute(TNEFProperty.ID_AIDOWNER));
|
||||||
assertNull(msg.getMessageAttribute(TNEFProperty.ID_ATTACHDATA));
|
assertNull(msg.getMessageAttribute(TNEFProperty.ID_ATTACHDATA));
|
||||||
|
|
||||||
// Now check the details of one or two
|
// Now check the details of one or two
|
||||||
assertEquals(
|
assertEquals(
|
||||||
0x010000,
|
0x010000,
|
||||||
LittleEndian.getInt( msg.getMessageAttribute(TNEFProperty.ID_TNEFVERSION).getData() )
|
LittleEndian.getInt(msg.getMessageAttribute(TNEFProperty.ID_TNEFVERSION).getData())
|
||||||
);
|
);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"IPM.Microsoft Mail.Note\0",
|
"IPM.Microsoft Mail.Note\0",
|
||||||
new String(msg.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS).getData(), "ASCII")
|
new String(msg.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS).getData(), "ASCII")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBasicMessageMAPIAttributes() throws Exception {
|
@Test
|
||||||
HMEFMessage msg = new HMEFMessage(
|
public void testBasicMessageMAPIAttributes() throws Exception {
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
HMEFMessage msg = new HMEFMessage(
|
||||||
);
|
_samples.openResourceAsStream("quick-winmail.dat")
|
||||||
|
);
|
||||||
|
|
||||||
assertEquals("This is a test message", msg.getSubject());
|
assertEquals("This is a test message", msg.getSubject());
|
||||||
assertEquals("{\\rtf1", msg.getBody().substring(0, 6));
|
assertEquals("{\\rtf1", msg.getBody().substring(0, 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks that the compressed RTF message contents
|
* Checks that the compressed RTF message contents
|
||||||
* can be correctly extracted
|
* can be correctly extracted
|
||||||
*/
|
*/
|
||||||
public void testMessageContents() throws Exception {
|
@Test
|
||||||
HMEFMessage msg = new HMEFMessage(
|
public void testMessageContents() throws Exception {
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
HMEFMessage msg = new HMEFMessage(
|
||||||
);
|
_samples.openResourceAsStream("quick-winmail.dat")
|
||||||
|
);
|
||||||
|
|
||||||
// Firstly by byte
|
// Firstly by byte
|
||||||
MAPIRtfAttribute rtf = (MAPIRtfAttribute)
|
MAPIRtfAttribute rtf = (MAPIRtfAttribute)
|
||||||
msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
||||||
assertContents("message.rtf", rtf.getData());
|
assertContents("message.rtf", rtf.getData());
|
||||||
|
|
||||||
// Then by String
|
// Then by String
|
||||||
String contents = msg.getBody();
|
String contents = msg.getBody();
|
||||||
// It's all low bytes
|
// It's all low bytes
|
||||||
byte[] contentsBytes = contents.getBytes("ASCII");
|
byte[] contentsBytes = contents.getBytes("ASCII");
|
||||||
assertContents("message.rtf", contentsBytes);
|
assertContents("message.rtf", contentsBytes);
|
||||||
|
|
||||||
// try to get a message id that does not exist
|
// try to get a message id that does not exist
|
||||||
assertNull(msg.getMessageMAPIAttribute(MAPIProperty.AB_DEFAULT_DIR));
|
assertNull(msg.getMessageMAPIAttribute(MAPIProperty.AB_DEFAULT_DIR));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMessageSample1() throws Exception {
|
@Test
|
||||||
HMEFMessage msg = new HMEFMessage(
|
public void testMessageSample1() throws Exception {
|
||||||
_samples.openResourceAsStream("winmail-sample1.dat"));
|
HMEFMessage msg = new HMEFMessage(
|
||||||
|
_samples.openResourceAsStream("winmail-sample1.dat"));
|
||||||
|
|
||||||
// Firstly by byte
|
// Firstly by byte
|
||||||
MAPIRtfAttribute rtf = (MAPIRtfAttribute) msg
|
MAPIRtfAttribute rtf = (MAPIRtfAttribute) msg
|
||||||
.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
||||||
// assertContents("message.rtf", rtf.getData());
|
// assertContents("message.rtf", rtf.getData());
|
||||||
assertNotNull(rtf);
|
assertNotNull(rtf);
|
||||||
|
|
||||||
// Then by String
|
// Then by String
|
||||||
String contents = msg.getBody();
|
String contents = msg.getBody();
|
||||||
//System.out.println(contents);
|
//System.out.println(contents);
|
||||||
// It's all low bytes
|
// It's all low bytes
|
||||||
byte[] contentsBytes = contents.getBytes("ASCII");
|
byte[] contentsBytes = contents.getBytes("ASCII");
|
||||||
// assertContents("message.rtf", contentsBytes);
|
// assertContents("message.rtf", contentsBytes);
|
||||||
assertNotNull(contentsBytes);
|
assertNotNull(contentsBytes);
|
||||||
|
|
||||||
assertNotNull(msg.getSubject());
|
assertNotNull(msg.getSubject());
|
||||||
assertNotNull(msg.getBody());
|
assertNotNull(msg.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInvalidMessage() throws Exception {
|
@Test
|
||||||
InputStream str = new ByteArrayInputStream(new byte[] {0, 0, 0, 0});
|
public void testInvalidMessage() throws Exception {
|
||||||
try {
|
InputStream str = new ByteArrayInputStream(new byte[]{0, 0, 0, 0});
|
||||||
assertNotNull(new HMEFMessage(str));
|
try {
|
||||||
fail("Should catch an exception here");
|
assertNotNull(new HMEFMessage(str));
|
||||||
} catch (IllegalArgumentException e) {
|
fail("Should catch an exception here");
|
||||||
assertTrue(e.getMessage().contains("TNEF signature not detected in file, expected 574529400 but got 0"));
|
} catch (IllegalArgumentException e) {
|
||||||
}
|
assertTrue(e.getMessage().contains("TNEF signature not detected in file, expected 574529400 but got 0"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoData() throws Exception {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
|
||||||
public void testNoData() throws Exception {
|
// Header
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
|
||||||
|
|
||||||
// Header
|
// field
|
||||||
LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
|
LittleEndian.putUShort(0, out);
|
||||||
|
|
||||||
// field
|
byte[] bytes = out.toByteArray();
|
||||||
LittleEndian.putUShort(0, out);
|
InputStream str = new ByteArrayInputStream(bytes);
|
||||||
|
HMEFMessage msg = new HMEFMessage(str);
|
||||||
|
assertNull(msg.getSubject());
|
||||||
|
assertNull(msg.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
byte[] bytes = out.toByteArray();
|
@Test
|
||||||
InputStream str = new ByteArrayInputStream(bytes);
|
public void testInvalidLevel() throws Exception {
|
||||||
HMEFMessage msg = new HMEFMessage(str);
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
assertNull(msg.getSubject());
|
|
||||||
assertNull(msg.getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testInvalidLevel() throws Exception {
|
// Header
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
|
||||||
|
|
||||||
// Header
|
// field
|
||||||
LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
|
LittleEndian.putUShort(0, out);
|
||||||
|
|
||||||
// field
|
// invalid level
|
||||||
LittleEndian.putUShort(0, out);
|
LittleEndian.putUShort(90, out);
|
||||||
|
|
||||||
// invalid level
|
byte[] bytes = out.toByteArray();
|
||||||
LittleEndian.putUShort(90, out);
|
InputStream str = new ByteArrayInputStream(bytes);
|
||||||
|
try {
|
||||||
|
assertNotNull(new HMEFMessage(str));
|
||||||
|
fail("Should catch an exception here");
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
assertTrue(e.getMessage().contains("Unhandled level 90"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
byte[] bytes = out.toByteArray();
|
@Test
|
||||||
InputStream str = new ByteArrayInputStream(bytes);
|
public void testCustomProperty() throws Exception {
|
||||||
try {
|
HMEFMessage msg = new HMEFMessage(
|
||||||
assertNotNull(new HMEFMessage(str));
|
_samples.openResourceAsStream("quick-winmail.dat")
|
||||||
fail("Should catch an exception here");
|
);
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
assertTrue(e.getMessage().contains("Unhandled level 90"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCustomProperty() throws Exception {
|
// Should have non-standard properties with IDs 0xE28 and 0xE29
|
||||||
HMEFMessage msg = new HMEFMessage(
|
boolean hasE28 = false;
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
boolean hasE29 = false;
|
||||||
);
|
for (MAPIAttribute attr : msg.getMessageMAPIAttributes()) {
|
||||||
|
if (attr.getProperty().id == 0xe28) hasE28 = true;
|
||||||
|
if (attr.getProperty().id == 0xe29) hasE29 = true;
|
||||||
|
}
|
||||||
|
assertEquals(true, hasE28);
|
||||||
|
assertEquals(true, hasE29);
|
||||||
|
|
||||||
// Should have non-standard properties with IDs 0xE28 and 0xE29
|
// Ensure we can fetch those as custom ones
|
||||||
boolean hasE28 = false;
|
MAPIProperty propE28 = MAPIProperty.createCustom(0xe28, Types.ASCII_STRING, "Custom E28");
|
||||||
boolean hasE29 = false;
|
MAPIProperty propE29 = MAPIProperty.createCustom(0xe29, Types.ASCII_STRING, "Custom E29");
|
||||||
for (MAPIAttribute attr : msg.getMessageMAPIAttributes()) {
|
assertNotNull(msg.getMessageMAPIAttribute(propE28));
|
||||||
if (attr.getProperty().id == 0xe28) hasE28 = true;
|
assertNotNull(msg.getMessageMAPIAttribute(propE29));
|
||||||
if (attr.getProperty().id == 0xe29) hasE29 = true;
|
|
||||||
}
|
|
||||||
assertEquals(true, hasE28);
|
|
||||||
assertEquals(true, hasE29);
|
|
||||||
|
|
||||||
// Ensure we can fetch those as custom ones
|
assertEquals(MAPIStringAttribute.class, msg.getMessageMAPIAttribute(propE28).getClass());
|
||||||
MAPIProperty propE28 = MAPIProperty.createCustom(0xe28, Types.ASCII_STRING, "Custom E28");
|
assertEquals(
|
||||||
MAPIProperty propE29 = MAPIProperty.createCustom(0xe29, Types.ASCII_STRING, "Custom E29");
|
"Zimbra - Mark Rogers",
|
||||||
assertNotNull(msg.getMessageMAPIAttribute(propE28));
|
((MAPIStringAttribute) msg.getMessageMAPIAttribute(propE28)).getDataString().substring(10)
|
||||||
assertNotNull(msg.getMessageMAPIAttribute(propE29));
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assertContents(String filename, byte[] actual)
|
||||||
|
throws IOException {
|
||||||
|
try (InputStream stream = _samples.openResourceAsStream("quick-contents/" + filename)) {
|
||||||
|
byte[] expected = IOUtils.toByteArray(stream);
|
||||||
|
|
||||||
|
assertEquals(expected.length, actual.length);
|
||||||
|
for (int i = 0; i < expected.length; i++) {
|
||||||
|
assertEquals("Byte " + i + " wrong", expected[i], actual[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assertEquals(MAPIStringAttribute.class, msg.getMessageMAPIAttribute(propE28).getClass());
|
|
||||||
assertEquals(
|
|
||||||
"Zimbra - Mark Rogers",
|
|
||||||
((MAPIStringAttribute)msg.getMessageMAPIAttribute(propE28)).getDataString().substring(10)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
|
|
||||||
package org.apache.poi.hmef.attribute;
|
package org.apache.poi.hmef.attribute;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
|
@ -28,159 +31,159 @@ import org.apache.poi.hmef.HMEFMessage;
|
||||||
import org.apache.poi.hsmf.datatypes.MAPIProperty;
|
import org.apache.poi.hsmf.datatypes.MAPIProperty;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.LocaleUtil;
|
import org.apache.poi.util.LocaleUtil;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
public final class TestMAPIAttributes {
|
||||||
|
private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
|
||||||
|
private HMEFMessage quick;
|
||||||
|
private InputStream stream;
|
||||||
|
|
||||||
public final class TestMAPIAttributes extends TestCase {
|
@Before
|
||||||
private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
|
public void setUp() throws Exception {
|
||||||
private HMEFMessage quick;
|
stream = _samples.openResourceAsStream("quick-winmail.dat");
|
||||||
private InputStream stream;
|
quick = new HMEFMessage(stream);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@After
|
||||||
protected void setUp() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
super.setUp();
|
stream.close();
|
||||||
|
}
|
||||||
stream = _samples.openResourceAsStream("quick-winmail.dat");
|
|
||||||
quick = new HMEFMessage(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
protected void tearDown() throws Exception {
|
* Test counts
|
||||||
stream.close();
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCounts() throws Exception {
|
||||||
|
// Message should have 54
|
||||||
|
assertEquals(54, quick.getMessageMAPIAttributes().size());
|
||||||
|
|
||||||
super.tearDown();
|
// First attachment should have 22
|
||||||
}
|
assertEquals(22, quick.getAttachments().get(0).getMAPIAttributes().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test various general ones
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBasics() throws Exception {
|
||||||
|
// Try constructing two attributes
|
||||||
|
byte[] data = new byte[]{
|
||||||
|
// Level one, id 36867, type 6
|
||||||
|
0x01, 0x03, (byte) 0x90, 0x06, 0x00,
|
||||||
|
// Length 24
|
||||||
|
0x24, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
/**
|
// Three attributes
|
||||||
* Test counts
|
0x03, 0x00, 0x00, 0x00,
|
||||||
*/
|
// AlternateRecipientAllowed = 01 00
|
||||||
public void testCounts() throws Exception {
|
0x0B, 0x00, 0x02, 0x00,
|
||||||
// Message should have 54
|
0x01, 0x00, 0x00, 0x00,
|
||||||
assertEquals(54, quick.getMessageMAPIAttributes().size());
|
// Priority = 00 00 00 00
|
||||||
|
0x03, 0x00, 0x26, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
// ConversationTopic = Test
|
||||||
|
0x1E, 0x00, 0x70, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00,
|
||||||
|
(byte) 'T', (byte) 'e',
|
||||||
|
(byte) 's', (byte) 't',
|
||||||
|
// Checksum (may be wrong...)
|
||||||
|
0x01, 0x00
|
||||||
|
};
|
||||||
|
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||||
|
|
||||||
// First attachment should have 22
|
// Create it
|
||||||
assertEquals(22, quick.getAttachments().get(0).getMAPIAttributes().size());
|
int level = bais.read();
|
||||||
}
|
assertEquals(1, level);
|
||||||
|
TNEFAttribute attr = TNEFAttribute.create(bais);
|
||||||
|
|
||||||
/**
|
// Check it
|
||||||
* Test various general ones
|
assertNotNull(attr);
|
||||||
*/
|
assertEquals(TNEFMAPIAttribute.class, attr.getClass());
|
||||||
public void testBasics() throws Exception {
|
|
||||||
// Try constructing two attributes
|
|
||||||
byte[] data = new byte[] {
|
|
||||||
// Level one, id 36867, type 6
|
|
||||||
0x01, 0x03, (byte)0x90, 0x06, 0x00,
|
|
||||||
// Length 24
|
|
||||||
0x24, 0x00, 0x00, 0x00,
|
|
||||||
|
|
||||||
// Three attributes
|
TNEFMAPIAttribute mapi = (TNEFMAPIAttribute) attr;
|
||||||
0x03, 0x00, 0x00, 0x00,
|
assertEquals(3, mapi.getMAPIAttributes().size());
|
||||||
// AlternateRecipientAllowed = 01 00
|
|
||||||
0x0B, 0x00, 0x02, 0x00,
|
|
||||||
0x01, 0x00, 0x00, 0x00,
|
|
||||||
// Priority = 00 00 00 00
|
|
||||||
0x03, 0x00, 0x26, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
// ConversationTopic = Test
|
|
||||||
0x1E, 0x00, 0x70, 0x00,
|
|
||||||
0x01, 0x00, 0x00, 0x00,
|
|
||||||
0x04, 0x00, 0x00, 0x00,
|
|
||||||
(byte)'T', (byte)'e',
|
|
||||||
(byte)'s', (byte)'t',
|
|
||||||
// Checksum (may be wrong...)
|
|
||||||
0x01, 0x00
|
|
||||||
};
|
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
|
||||||
|
|
||||||
// Create it
|
assertEquals(
|
||||||
int level = bais.read();
|
MAPIProperty.ALTERNATE_RECIPIENT_ALLOWED,
|
||||||
assertEquals(1, level);
|
mapi.getMAPIAttributes().get(0).getProperty()
|
||||||
TNEFAttribute attr = TNEFAttribute.create(bais);
|
);
|
||||||
|
assertEquals(1, LittleEndian.getUShort(
|
||||||
|
mapi.getMAPIAttributes().get(0).getData()
|
||||||
|
));
|
||||||
|
|
||||||
// Check it
|
assertEquals(
|
||||||
assertNotNull(attr);
|
MAPIProperty.PRIORITY,
|
||||||
assertEquals(TNEFMAPIAttribute.class, attr.getClass());
|
mapi.getMAPIAttributes().get(1).getProperty()
|
||||||
|
);
|
||||||
|
assertEquals(0, LittleEndian.getUShort(
|
||||||
|
mapi.getMAPIAttributes().get(1).getData()
|
||||||
|
));
|
||||||
|
|
||||||
TNEFMAPIAttribute mapi = (TNEFMAPIAttribute)attr;
|
assertEquals(
|
||||||
assertEquals(3, mapi.getMAPIAttributes().size());
|
MAPIProperty.CONVERSATION_TOPIC,
|
||||||
|
mapi.getMAPIAttributes().get(2).getProperty()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
"Test",
|
||||||
|
((MAPIStringAttribute) mapi.getMAPIAttributes().get(2)).getDataString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
assertEquals(
|
/**
|
||||||
MAPIProperty.ALTERNATE_RECIPIENT_ALLOWED,
|
* Test String, Date and RTF ones
|
||||||
mapi.getMAPIAttributes().get(0).getProperty()
|
*/
|
||||||
);
|
@Test
|
||||||
assertEquals(1, LittleEndian.getUShort(
|
public void testTyped() throws Exception {
|
||||||
mapi.getMAPIAttributes().get(0).getData()
|
MAPIAttribute attr;
|
||||||
));
|
|
||||||
|
|
||||||
assertEquals(
|
// String
|
||||||
MAPIProperty.PRIORITY,
|
// ConversationTopic -> This is a test message
|
||||||
mapi.getMAPIAttributes().get(1).getProperty()
|
attr = quick.getMessageMAPIAttribute(MAPIProperty.CONVERSATION_TOPIC);
|
||||||
);
|
assertNotNull(attr);
|
||||||
assertEquals(0, LittleEndian.getUShort(
|
assertEquals(MAPIStringAttribute.class, attr.getClass());
|
||||||
mapi.getMAPIAttributes().get(1).getData()
|
|
||||||
));
|
|
||||||
|
|
||||||
assertEquals(
|
MAPIStringAttribute str = (MAPIStringAttribute) attr;
|
||||||
MAPIProperty.CONVERSATION_TOPIC,
|
assertEquals("This is a test message", str.getDataString());
|
||||||
mapi.getMAPIAttributes().get(2).getProperty()
|
|
||||||
);
|
|
||||||
assertEquals(
|
|
||||||
"Test",
|
|
||||||
((MAPIStringAttribute)mapi.getMAPIAttributes().get(2)).getDataString()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Date
|
||||||
* Test String, Date and RTF ones
|
// (Unknown/Custom) 32955 -> Wed Dec 15 2010 @ 14:46:31 UTC
|
||||||
*/
|
attr = null;
|
||||||
public void testTyped() throws Exception {
|
for (MAPIAttribute a : quick.getMessageMAPIAttributes()) {
|
||||||
MAPIAttribute attr;
|
if (a.getProperty().id == 32955) {
|
||||||
|
attr = a;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertNotNull(attr);
|
||||||
|
assertEquals(MAPIDateAttribute.class, attr.getClass());
|
||||||
|
|
||||||
// String
|
MAPIDateAttribute date = (MAPIDateAttribute) attr;
|
||||||
// ConversationTopic -> This is a test message
|
DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
|
||||||
attr = quick.getMessageMAPIAttribute(MAPIProperty.CONVERSATION_TOPIC);
|
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
||||||
assertNotNull(attr);
|
assertEquals("15-Dec-2010 14:46:31", fmt.format(date.getDate()));
|
||||||
assertEquals(MAPIStringAttribute.class, attr.getClass());
|
|
||||||
|
|
||||||
MAPIStringAttribute str = (MAPIStringAttribute)attr;
|
// RTF
|
||||||
assertEquals("This is a test message", str.getDataString());
|
// RtfCompressed -> {\rtf1...
|
||||||
|
attr = quick.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
||||||
|
assertNotNull(attr);
|
||||||
|
assertEquals(MAPIRtfAttribute.class, attr.getClass());
|
||||||
|
|
||||||
// Date
|
MAPIRtfAttribute rtf = (MAPIRtfAttribute) attr;
|
||||||
// (Unknown/Custom) 32955 -> Wed Dec 15 2010 @ 14:46:31 UTC
|
assertEquals("{\\rtf1", rtf.getDataString().substring(0, 6));
|
||||||
attr = null;
|
}
|
||||||
for(MAPIAttribute a : quick.getMessageMAPIAttributes()) {
|
|
||||||
if(a.getProperty().id == 32955) {
|
|
||||||
attr = a;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertNotNull(attr);
|
|
||||||
assertEquals(MAPIDateAttribute.class, attr.getClass());
|
|
||||||
|
|
||||||
MAPIDateAttribute date = (MAPIDateAttribute)attr;
|
/**
|
||||||
DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
|
* Check common ones via helper accessors
|
||||||
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
*/
|
||||||
assertEquals("15-Dec-2010 14:46:31", fmt.format(date.getDate()));
|
@Test
|
||||||
|
public void testCommon() throws Exception {
|
||||||
|
assertEquals("This is a test message", quick.getSubject());
|
||||||
|
|
||||||
// RTF
|
assertEquals("quick.doc", quick.getAttachments().get(0).getLongFilename());
|
||||||
// RtfCompressed -> {\rtf1...
|
assertEquals(".doc", quick.getAttachments().get(0).getExtension());
|
||||||
attr = quick.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
}
|
||||||
assertNotNull(attr);
|
|
||||||
assertEquals(MAPIRtfAttribute.class, attr.getClass());
|
|
||||||
|
|
||||||
MAPIRtfAttribute rtf = (MAPIRtfAttribute)attr;
|
|
||||||
assertEquals("{\\rtf1", rtf.getDataString().substring(0, 6));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check common ones via helper accessors
|
|
||||||
*/
|
|
||||||
public void testCommon() throws Exception {
|
|
||||||
assertEquals("This is a test message", quick.getSubject());
|
|
||||||
|
|
||||||
assertEquals("quick.doc", quick.getAttachments().get(0).getLongFilename());
|
|
||||||
assertEquals(".doc", quick.getAttachments().get(0).getExtension());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,11 @@
|
||||||
|
|
||||||
package org.apache.poi.hmef.attribute;
|
package org.apache.poi.hmef.attribute;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -28,182 +32,186 @@ import org.apache.poi.hmef.HMEFMessage;
|
||||||
import org.apache.poi.hsmf.datatypes.MAPIProperty;
|
import org.apache.poi.hsmf.datatypes.MAPIProperty;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.LocaleUtil;
|
import org.apache.poi.util.LocaleUtil;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
public final class TestTNEFAttributes {
|
||||||
|
private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
|
||||||
|
private HMEFMessage quick;
|
||||||
|
|
||||||
public final class TestTNEFAttributes extends TestCase {
|
@Before
|
||||||
private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance();
|
public void setUp() throws Exception {
|
||||||
private HMEFMessage quick;
|
try (InputStream is = _samples.openResourceAsStream("quick-winmail.dat")) {
|
||||||
|
quick = new HMEFMessage(is);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
protected void setUp() throws Exception {
|
* Test counts
|
||||||
super.setUp();
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCounts() throws Exception {
|
||||||
|
// The message should have 4 attributes
|
||||||
|
assertEquals(4, quick.getMessageAttributes().size());
|
||||||
|
|
||||||
quick = new HMEFMessage(
|
// Each attachment should have 6 attributes
|
||||||
_samples.openResourceAsStream("quick-winmail.dat")
|
for (Attachment attach : quick.getAttachments()) {
|
||||||
);
|
assertEquals(6, attach.getAttributes().size());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test counts
|
* Test the basics
|
||||||
*/
|
*/
|
||||||
public void testCounts() throws Exception {
|
@Test
|
||||||
// The message should have 4 attributes
|
public void testBasics() throws Exception {
|
||||||
assertEquals(4, quick.getMessageAttributes().size());
|
// An int one
|
||||||
|
assertEquals(
|
||||||
|
0x010000,
|
||||||
|
LittleEndian.getInt(quick.getMessageAttribute(TNEFProperty.ID_TNEFVERSION).getData())
|
||||||
|
);
|
||||||
|
|
||||||
// Each attachment should have 6 attributes
|
// Claims not to be text, but really is
|
||||||
for(Attachment attach : quick.getAttachments()) {
|
assertEquals(
|
||||||
assertEquals(6, attach.getAttributes().size());
|
"IPM.Microsoft Mail.Note\0",
|
||||||
}
|
new String(quick.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS).getData(), "ASCII")
|
||||||
}
|
);
|
||||||
|
|
||||||
/**
|
// Try constructing two attributes
|
||||||
* Test the basics
|
byte[] data = new byte[]{
|
||||||
*/
|
// Level one, id 36870, type 8
|
||||||
public void testBasics() throws Exception {
|
0x01, 0x06, (byte) 0x90, 0x08, 0x00,
|
||||||
// An int one
|
// Length 4
|
||||||
assertEquals(
|
0x04, 0x00, 0x00, 0x00,
|
||||||
0x010000,
|
// Data
|
||||||
LittleEndian.getInt( quick.getMessageAttribute(TNEFProperty.ID_TNEFVERSION).getData() )
|
0x00, 0x00, 0x01, 0x00,
|
||||||
);
|
// Checksum
|
||||||
|
0x01, 0x00,
|
||||||
|
|
||||||
// Claims not to be text, but really is
|
// level one, id 36871, type 6
|
||||||
assertEquals(
|
0x01, 0x07, (byte) 0x90, 0x06, 0x00,
|
||||||
"IPM.Microsoft Mail.Note\0",
|
// Length 8
|
||||||
new String(quick.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS).getData(), "ASCII")
|
0x08, 0x00, 0x00, 0x00,
|
||||||
);
|
// Data
|
||||||
|
(byte) 0xe4, 0x04, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Checksum
|
||||||
|
(byte) 0xe8, 0x00
|
||||||
|
};
|
||||||
|
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||||
|
|
||||||
// Try constructing two attributes
|
// Create them
|
||||||
byte[] data = new byte[] {
|
int level = bais.read();
|
||||||
// Level one, id 36870, type 8
|
assertEquals(1, level);
|
||||||
0x01, 0x06, (byte)0x90, 0x08, 0x00,
|
TNEFAttribute attr1 = TNEFAttribute.create(bais);
|
||||||
// Length 4
|
|
||||||
0x04, 0x00, 0x00, 0x00,
|
|
||||||
// Data
|
|
||||||
0x00, 0x00, 0x01, 0x00,
|
|
||||||
// Checksum
|
|
||||||
0x01, 0x00,
|
|
||||||
|
|
||||||
// level one, id 36871, type 6
|
level = bais.read();
|
||||||
0x01, 0x07, (byte)0x90, 0x06, 0x00,
|
assertEquals(1, level);
|
||||||
// Length 8
|
TNEFAttribute attr2 = TNEFAttribute.create(bais);
|
||||||
0x08, 0x00, 0x00, 0x00,
|
|
||||||
// Data
|
|
||||||
(byte)0xe4, 0x04, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
// Checksum
|
|
||||||
(byte)0xe8, 0x00
|
|
||||||
};
|
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
|
||||||
|
|
||||||
// Create them
|
assertEquals(-1, bais.read());
|
||||||
int level = bais.read();
|
|
||||||
assertEquals(1, level);
|
|
||||||
TNEFAttribute attr1 = TNEFAttribute.create(bais);
|
|
||||||
|
|
||||||
level = bais.read();
|
// Check them
|
||||||
assertEquals(1, level);
|
assertEquals(TNEFProperty.ID_TNEFVERSION, attr1.getProperty());
|
||||||
TNEFAttribute attr2 = TNEFAttribute.create(bais);
|
assertEquals(8, attr1.getType());
|
||||||
|
assertEquals(4, attr1.getData().length);
|
||||||
|
assertEquals(0x010000, LittleEndian.getInt(attr1.getData()));
|
||||||
|
|
||||||
assertEquals(-1, bais.read());
|
assertEquals(TNEFProperty.ID_OEMCODEPAGE, attr2.getProperty());
|
||||||
|
assertEquals(6, attr2.getType());
|
||||||
|
assertEquals(8, attr2.getData().length);
|
||||||
|
assertEquals(0x04e4, LittleEndian.getInt(attr2.getData()));
|
||||||
|
}
|
||||||
|
|
||||||
// Check them
|
/**
|
||||||
assertEquals(TNEFProperty.ID_TNEFVERSION, attr1.getProperty());
|
* Test string based ones
|
||||||
assertEquals(8, attr1.getType());
|
*/
|
||||||
assertEquals(4, attr1.getData().length);
|
@Test
|
||||||
assertEquals(0x010000, LittleEndian.getInt( attr1.getData() ));
|
public void testString() throws Exception {
|
||||||
|
TNEFAttribute attr = quick.getAttachments().get(0).getAttribute(
|
||||||
|
TNEFProperty.ID_ATTACHTITLE
|
||||||
|
);
|
||||||
|
assertNotNull(attr);
|
||||||
|
assertEquals(TNEFStringAttribute.class, attr.getClass());
|
||||||
|
|
||||||
assertEquals(TNEFProperty.ID_OEMCODEPAGE, attr2.getProperty());
|
// It is a null terminated string
|
||||||
assertEquals(6, attr2.getType());
|
assertEquals("quick.doc\u0000", new String(attr.getData(), "ASCII"));
|
||||||
assertEquals(8, attr2.getData().length);
|
|
||||||
assertEquals(0x04e4, LittleEndian.getInt( attr2.getData() ));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// But when we ask for the string, that is sorted for us
|
||||||
* Test string based ones
|
TNEFStringAttribute str = (TNEFStringAttribute) attr;
|
||||||
*/
|
assertEquals("quick.doc", str.getString());
|
||||||
public void testString() throws Exception {
|
}
|
||||||
TNEFAttribute attr = quick.getAttachments().get(0).getAttribute(
|
|
||||||
TNEFProperty.ID_ATTACHTITLE
|
|
||||||
);
|
|
||||||
assertNotNull(attr);
|
|
||||||
assertEquals(TNEFStringAttribute.class, attr.getClass());
|
|
||||||
|
|
||||||
// It is a null terminated string
|
/**
|
||||||
assertEquals("quick.doc\u0000", new String(attr.getData(), "ASCII"));
|
* Test date based ones
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDate() throws Exception {
|
||||||
|
TNEFAttribute attr = quick.getAttachments().get(0).getAttribute(
|
||||||
|
TNEFProperty.ID_ATTACHMODIFYDATE
|
||||||
|
);
|
||||||
|
assertNotNull(attr);
|
||||||
|
assertEquals(TNEFDateAttribute.class, attr.getClass());
|
||||||
|
|
||||||
// But when we ask for the string, that is sorted for us
|
// It is a series of date parts
|
||||||
TNEFStringAttribute str = (TNEFStringAttribute)attr;
|
// Weds 28th April 2010 @ 12:40:56 UTC
|
||||||
assertEquals("quick.doc", str.getString());
|
assertEquals(2010, LittleEndian.getUShort(attr.getData(), 0));
|
||||||
}
|
assertEquals(04, LittleEndian.getUShort(attr.getData(), 2));
|
||||||
|
assertEquals(28, LittleEndian.getUShort(attr.getData(), 4));
|
||||||
|
assertEquals(12, LittleEndian.getUShort(attr.getData(), 6));
|
||||||
|
assertEquals(40, LittleEndian.getUShort(attr.getData(), 8));
|
||||||
|
assertEquals(56, LittleEndian.getUShort(attr.getData(), 10));
|
||||||
|
assertEquals(3, LittleEndian.getUShort(attr.getData(), 12)); // Weds
|
||||||
|
|
||||||
/**
|
// Ask for it as a Java date, and have it converted
|
||||||
* Test date based ones
|
// Pick a predictable format + location + timezone
|
||||||
*/
|
TNEFDateAttribute date = (TNEFDateAttribute) attr;
|
||||||
public void testDate() throws Exception {
|
DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
|
||||||
TNEFAttribute attr = quick.getAttachments().get(0).getAttribute(
|
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
||||||
TNEFProperty.ID_ATTACHMODIFYDATE
|
assertEquals("28-Apr-2010 12:40:56", fmt.format(date.getDate()));
|
||||||
);
|
}
|
||||||
assertNotNull(attr);
|
|
||||||
assertEquals(TNEFDateAttribute.class, attr.getClass());
|
|
||||||
|
|
||||||
// It is a series of date parts
|
/**
|
||||||
// Weds 28th April 2010 @ 12:40:56 UTC
|
* Test a bit of mapi
|
||||||
assertEquals(2010, LittleEndian.getUShort(attr.getData(), 0));
|
*/
|
||||||
assertEquals(04, LittleEndian.getUShort(attr.getData(), 2));
|
@Test
|
||||||
assertEquals(28, LittleEndian.getUShort(attr.getData(), 4));
|
public void testMAPI() throws Exception {
|
||||||
assertEquals(12, LittleEndian.getUShort(attr.getData(), 6));
|
// Message MAPI
|
||||||
assertEquals(40, LittleEndian.getUShort(attr.getData(), 8));
|
TNEFAttribute attr = quick.getMessageAttribute(
|
||||||
assertEquals(56, LittleEndian.getUShort(attr.getData(), 10));
|
TNEFProperty.ID_MAPIPROPERTIES
|
||||||
assertEquals(3, LittleEndian.getUShort(attr.getData(), 12)); // Weds
|
);
|
||||||
|
assertNotNull(attr);
|
||||||
|
assertEquals(TNEFMAPIAttribute.class, attr.getClass());
|
||||||
|
|
||||||
// Ask for it as a Java date, and have it converted
|
TNEFMAPIAttribute mapi = (TNEFMAPIAttribute) attr;
|
||||||
// Pick a predictable format + location + timezone
|
assertEquals(54, mapi.getMAPIAttributes().size());
|
||||||
TNEFDateAttribute date = (TNEFDateAttribute)attr;
|
assertEquals(
|
||||||
DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
|
MAPIProperty.ALTERNATE_RECIPIENT_ALLOWED,
|
||||||
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
mapi.getMAPIAttributes().get(0).getProperty()
|
||||||
assertEquals("28-Apr-2010 12:40:56", fmt.format(date.getDate()));
|
);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test a bit of mapi
|
|
||||||
*/
|
|
||||||
public void testMAPI() throws Exception {
|
|
||||||
// Message MAPI
|
|
||||||
TNEFAttribute attr = quick.getMessageAttribute(
|
|
||||||
TNEFProperty.ID_MAPIPROPERTIES
|
|
||||||
);
|
|
||||||
assertNotNull(attr);
|
|
||||||
assertEquals(TNEFMAPIAttribute.class, attr.getClass());
|
|
||||||
|
|
||||||
TNEFMAPIAttribute mapi = (TNEFMAPIAttribute)attr;
|
|
||||||
assertEquals(54, mapi.getMAPIAttributes().size());
|
|
||||||
assertEquals(
|
|
||||||
MAPIProperty.ALTERNATE_RECIPIENT_ALLOWED,
|
|
||||||
mapi.getMAPIAttributes().get(0).getProperty()
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// Attribute MAPI
|
// Attribute MAPI
|
||||||
attr = quick.getAttachments().get(0).getAttribute(
|
attr = quick.getAttachments().get(0).getAttribute(
|
||||||
TNEFProperty.ID_ATTACHMENT
|
TNEFProperty.ID_ATTACHMENT
|
||||||
);
|
);
|
||||||
assertNotNull(attr);
|
assertNotNull(attr);
|
||||||
assertEquals(TNEFMAPIAttribute.class, attr.getClass());
|
assertEquals(TNEFMAPIAttribute.class, attr.getClass());
|
||||||
|
|
||||||
mapi = (TNEFMAPIAttribute)attr;
|
mapi = (TNEFMAPIAttribute) attr;
|
||||||
assertEquals(22, mapi.getMAPIAttributes().size());
|
assertEquals(22, mapi.getMAPIAttributes().size());
|
||||||
assertEquals(
|
assertEquals(
|
||||||
MAPIProperty.ATTACH_SIZE,
|
MAPIProperty.ATTACH_SIZE,
|
||||||
mapi.getMAPIAttributes().get(0).getProperty()
|
mapi.getMAPIAttributes().get(0).getProperty()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test common ones via helpers
|
* Test common ones via helpers
|
||||||
*/
|
*/
|
||||||
public void testCommon() throws Exception {
|
@Test
|
||||||
assertEquals("This is a test message", quick.getSubject());
|
public void testCommon() throws Exception {
|
||||||
assertEquals("quick.doc", quick.getAttachments().get(0).getFilename());
|
assertEquals("This is a test message", quick.getSubject());
|
||||||
}
|
assertEquals("quick.doc", quick.getAttachments().get(0).getFilename());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,31 +20,38 @@
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.hmef.dev;
|
package org.apache.poi.hmef.dev;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import org.apache.poi.POIDataSamples;
|
||||||
|
import org.apache.poi.util.NullOutputStream;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public class TestHMEFDumper {
|
public class TestHMEFDumper {
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void noArguments() throws Exception {
|
public void noArguments() throws Exception {
|
||||||
HMEFDumper.main(new String[] {});
|
doMain();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void main() throws Exception {
|
public void main() throws Exception {
|
||||||
File file = POIDataSamples.getHMEFInstance().getFile("quick-winmail.dat");
|
File file = POIDataSamples.getHMEFInstance().getFile("quick-winmail.dat");
|
||||||
HMEFDumper.main(new String[] {
|
doMain(file.getAbsolutePath());
|
||||||
file.getAbsolutePath()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void mainFull() throws Exception {
|
public void mainFull() throws Exception {
|
||||||
File file = POIDataSamples.getHMEFInstance().getFile("quick-winmail.dat");
|
File file = POIDataSamples.getHMEFInstance().getFile("quick-winmail.dat");
|
||||||
HMEFDumper.main(new String[] {
|
doMain("--full", file.getAbsolutePath());
|
||||||
"--full",
|
}
|
||||||
file.getAbsolutePath()
|
|
||||||
});
|
private static void doMain(String... args) throws Exception {
|
||||||
|
PrintStream ps = System.out;
|
||||||
|
try {
|
||||||
|
System.setOut(new PrintStream(new NullOutputStream(), true, "UTF-8"));
|
||||||
|
HMEFDumper.main(args);
|
||||||
|
} finally {
|
||||||
|
System.setOut(ps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue