mirror of https://github.com/apache/poi.git
Bug 52400: fix handling some types of TNEF files, make HMEFMessage.HEADER_SIGNATURE int as it is handled as int everywhere, move .dat files to HMEF sample dir, cover some border cases in HMEFMessage, add another .dat sample file
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1538353 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cf4da543b8
commit
16f576c335
|
@ -39,7 +39,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
* http://search.cpan.org/dist/Convert-TNEF/
|
||||
*/
|
||||
public final class HMEFMessage {
|
||||
public static final long HEADER_SIGNATURE = 0x223e9f78;
|
||||
public static final int HEADER_SIGNATURE = 0x223e9f78;
|
||||
|
||||
private int fileId;
|
||||
private List<TNEFAttribute> messageAttributes = new ArrayList<TNEFAttribute>();
|
||||
|
@ -48,7 +48,7 @@ public final class HMEFMessage {
|
|||
|
||||
public HMEFMessage(InputStream inp) throws IOException {
|
||||
// Check the signature matches
|
||||
long sig = LittleEndian.readInt(inp);
|
||||
int sig = LittleEndian.readInt(inp);
|
||||
if(sig != HEADER_SIGNATURE) {
|
||||
throw new IllegalArgumentException(
|
||||
"TNEF signature not detected in file, " +
|
||||
|
@ -60,42 +60,59 @@ public final class HMEFMessage {
|
|||
fileId = LittleEndian.readUShort(inp);
|
||||
|
||||
// Now begin processing the contents
|
||||
process(inp, 0);
|
||||
process(inp);
|
||||
}
|
||||
|
||||
private void process(InputStream inp, int lastLevel) throws IOException {
|
||||
// Fetch the level
|
||||
int level = inp.read();
|
||||
if(level == TNEFProperty.LEVEL_END_OF_FILE) {
|
||||
return;
|
||||
}
|
||||
|
||||
private void process(InputStream inp) throws IOException {
|
||||
int level;
|
||||
do {
|
||||
// Fetch the level
|
||||
level = inp.read();
|
||||
|
||||
// Decide what to attach it to, based on the levels and IDs
|
||||
switch (level) {
|
||||
case TNEFProperty.LEVEL_MESSAGE:
|
||||
processMessage(inp);
|
||||
break;
|
||||
case TNEFProperty.LEVEL_ATTACHMENT:
|
||||
processAttachment(inp);
|
||||
break;
|
||||
// ignore trailing newline
|
||||
case '\r':
|
||||
case '\n':
|
||||
case TNEFProperty.LEVEL_END_OF_FILE:
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unhandled level " + level);
|
||||
}
|
||||
} while (level != TNEFProperty.LEVEL_END_OF_FILE);
|
||||
}
|
||||
|
||||
void processMessage(InputStream inp) throws IOException {
|
||||
// Build the attribute
|
||||
TNEFAttribute attr = TNEFAttribute.create(inp);
|
||||
|
||||
// Decide what to attach it to, based on the levels and IDs
|
||||
if(level == TNEFProperty.LEVEL_MESSAGE) {
|
||||
messageAttributes.add(attr);
|
||||
|
||||
if(attr instanceof TNEFMAPIAttribute) {
|
||||
TNEFMAPIAttribute tnefMAPI = (TNEFMAPIAttribute)attr;
|
||||
mapiAttributes.addAll( tnefMAPI.getMAPIAttributes() );
|
||||
}
|
||||
} else if(level == TNEFProperty.LEVEL_ATTACHMENT) {
|
||||
// Previous attachment or a new one?
|
||||
if(attachments.size() == 0 || attr.getProperty() == TNEFProperty.ID_ATTACHRENDERDATA) {
|
||||
attachments.add(new Attachment());
|
||||
}
|
||||
|
||||
// Save the attribute for it
|
||||
Attachment attach = attachments.get(attachments.size()-1);
|
||||
attach.addAttribute(attr);
|
||||
} else {
|
||||
throw new IllegalStateException("Unhandled level " + level);
|
||||
|
||||
messageAttributes.add(attr);
|
||||
|
||||
if (attr instanceof TNEFMAPIAttribute) {
|
||||
TNEFMAPIAttribute tnefMAPI = (TNEFMAPIAttribute) attr;
|
||||
mapiAttributes.addAll(tnefMAPI.getMAPIAttributes());
|
||||
}
|
||||
|
||||
// Handle the next one down
|
||||
process(inp, level);
|
||||
}
|
||||
|
||||
void processAttachment(InputStream inp) throws IOException {
|
||||
// Build the attribute
|
||||
TNEFAttribute attr = TNEFAttribute.create(inp);
|
||||
|
||||
// Previous attachment or a new one?
|
||||
if (attachments.isEmpty()
|
||||
|| attr.getProperty() == TNEFProperty.ID_ATTACHRENDERDATA) {
|
||||
attachments.add(new Attachment());
|
||||
}
|
||||
|
||||
// Save the attribute for it
|
||||
Attachment attach = attachments.get(attachments.size() - 1);
|
||||
attach.addAttribute(attr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,8 +23,8 @@ import java.io.InputStream;
|
|||
import java.util.List;
|
||||
|
||||
import org.apache.poi.hmef.HMEFMessage;
|
||||
import org.apache.poi.hmef.attribute.TNEFAttribute;
|
||||
import org.apache.poi.hmef.attribute.MAPIAttribute;
|
||||
import org.apache.poi.hmef.attribute.TNEFAttribute;
|
||||
import org.apache.poi.hmef.attribute.TNEFDateAttribute;
|
||||
import org.apache.poi.hmef.attribute.TNEFProperty;
|
||||
import org.apache.poi.hmef.attribute.TNEFStringAttribute;
|
||||
|
@ -62,7 +62,7 @@ public final class HMEFDumper {
|
|||
this.inp = inp;
|
||||
|
||||
// Check the signature matches
|
||||
long sig = LittleEndian.readInt(inp);
|
||||
int sig = LittleEndian.readInt(inp);
|
||||
if(sig != HMEFMessage.HEADER_SIGNATURE) {
|
||||
throw new IllegalArgumentException(
|
||||
"TNEF signature not detected in file, " +
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package org.apache.poi.hmef;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.hmef.attribute.MAPIAttribute;
|
||||
import org.apache.poi.hmef.attribute.TNEFAttribute;
|
||||
import org.apache.poi.hmef.attribute.TNEFProperty;
|
||||
import org.apache.poi.hsmf.datatypes.MAPIProperty;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
public class TestBugs extends TestCase {
|
||||
public void test52400ReadSimpleTNEF() throws Exception {
|
||||
POIDataSamples samples = POIDataSamples.getHMEFInstance();
|
||||
String testFile = "bug52400-winmail-simple.dat";
|
||||
HMEFMessage tnefDat = new HMEFMessage(samples.openResourceAsStream(testFile));
|
||||
MAPIAttribute bodyHtml = tnefDat.getMessageMAPIAttribute(MAPIProperty.BODY_HTML);
|
||||
String bodyStr = new String(bodyHtml.getData(), getEncoding(tnefDat));
|
||||
assertTrue(bodyStr.contains("This is the message body."));
|
||||
}
|
||||
|
||||
public void test52400ReadAttachedTNEF() throws Exception {
|
||||
POIDataSamples samples = POIDataSamples.getHMEFInstance();
|
||||
String testFile = "bug52400-winmail-with-attachments.dat";
|
||||
HMEFMessage tnefDat = new HMEFMessage(samples.openResourceAsStream(testFile));
|
||||
MAPIAttribute bodyHtml = tnefDat.getMessageMAPIAttribute(MAPIProperty.BODY_HTML);
|
||||
String bodyStr = new String(bodyHtml.getData(), getEncoding(tnefDat));
|
||||
assertTrue(bodyStr.contains("There are also two attachments."));
|
||||
assertEquals(2, tnefDat.getAttachments().size());
|
||||
}
|
||||
|
||||
private String getEncoding(HMEFMessage tnefDat) {
|
||||
TNEFAttribute oemCP = tnefDat.getMessageAttribute(TNEFProperty.ID_OEMCODEPAGE);
|
||||
MAPIAttribute cpId = tnefDat.getMessageMAPIAttribute(MAPIProperty.INTERNET_CPID);
|
||||
int codePage = 1252;
|
||||
if (oemCP != null) {
|
||||
codePage = LittleEndian.getInt(oemCP.getData());
|
||||
} else if (cpId != null) {
|
||||
codePage = LittleEndian.getInt(cpId.getData());
|
||||
}
|
||||
switch (codePage) {
|
||||
// see http://en.wikipedia.org/wiki/Code_page for more
|
||||
case 1252: return "Windows-1252";
|
||||
case 20127: return "US-ASCII";
|
||||
default: return "cp"+codePage;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,10 @@
|
|||
|
||||
package org.apache.poi.hmef;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.hmef.attribute.MAPIRtfAttribute;
|
||||
import org.apache.poi.hmef.attribute.TNEFProperty;
|
||||
import org.apache.poi.hsmf.datatypes.MAPIProperty;
|
||||
|
@ -119,5 +123,80 @@ public final class TestHMEFMessage extends HMEFTest {
|
|||
// It's all low bytes
|
||||
byte[] contentsBytes = contents.getBytes("ASCII");
|
||||
assertContents("message.rtf", contentsBytes);
|
||||
|
||||
// try to get a message id that does not exist
|
||||
assertNull(msg.getMessageMAPIAttribute(MAPIProperty.AB_DEFAULT_DIR));
|
||||
}
|
||||
|
||||
public void testMessageSample1() throws Exception {
|
||||
HMEFMessage msg = new HMEFMessage(
|
||||
_samples.openResourceAsStream("winmail-sample1.dat"));
|
||||
|
||||
// Firstly by byte
|
||||
MAPIRtfAttribute rtf = (MAPIRtfAttribute) msg
|
||||
.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
|
||||
// assertContents("message.rtf", rtf.getData());
|
||||
assertNotNull(rtf);
|
||||
|
||||
// Then by String
|
||||
String contents = msg.getBody();
|
||||
//System.out.println(contents);
|
||||
// It's all low bytes
|
||||
byte[] contentsBytes = contents.getBytes("ASCII");
|
||||
// assertContents("message.rtf", contentsBytes);
|
||||
assertNotNull(contentsBytes);
|
||||
|
||||
assertNotNull(msg.getSubject());
|
||||
assertNotNull(msg.getBody());
|
||||
}
|
||||
|
||||
public void testInvalidMessage() throws Exception {
|
||||
InputStream str = new ByteArrayInputStream(new byte[] {0, 0, 0, 0});
|
||||
try {
|
||||
assertNotNull(new HMEFMessage(str));
|
||||
fail("Should catch an exception here");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage().contains("TNEF signature not detected in file, expected 574529400 but got 0"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testNoData() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
|
||||
// Header
|
||||
LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
|
||||
|
||||
// field
|
||||
LittleEndian.putUShort(0, out);
|
||||
|
||||
byte[] bytes = out.toByteArray();
|
||||
InputStream str = new ByteArrayInputStream(bytes);
|
||||
HMEFMessage msg = new HMEFMessage(str);
|
||||
assertNull(msg.getSubject());
|
||||
assertNull(msg.getBody());
|
||||
}
|
||||
|
||||
public void testInvalidLevel() throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
|
||||
// Header
|
||||
LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
|
||||
|
||||
// field
|
||||
LittleEndian.putUShort(0, out);
|
||||
|
||||
// invalid level
|
||||
LittleEndian.putUShort(90, out);
|
||||
|
||||
byte[] bytes = out.toByteArray();
|
||||
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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue