Fix nullpointer when HTML body is empty

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@40 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2007-03-21 15:08:46 +00:00
parent 163e611bd1
commit 6a79873d29
1 changed files with 83 additions and 75 deletions

View File

@ -17,6 +17,7 @@ import org.w3c.tidy.Tidy;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.Element;
import javax.mail.MessagingException; import javax.mail.MessagingException;
import javax.mail.internet.MimeUtility; import javax.mail.internet.MimeUtility;
@ -1058,15 +1059,19 @@ public class ExchangeSession {
XmlDocument xmlDocument = new XmlDocument(); XmlDocument xmlDocument = new XmlDocument();
try { try {
Document w3cDocument = tidy.parseDOM(inputStream, null); Document w3cDocument = tidy.parseDOM(inputStream, null);
// Fix broken Office xml document with empty namespace Element documentElement = w3cDocument.getDocumentElement();
NamedNodeMap namedNodeMap = w3cDocument.getDocumentElement().getAttributes();
for (int i = 0; i < namedNodeMap.getLength(); i++) { if (documentElement != null) {
Node node = namedNodeMap.item(i); // Fix broken Office xml document with empty namespace
String nodeName = node.getNodeName(); NamedNodeMap namedNodeMap = w3cDocument.getDocumentElement().getAttributes();
String nodeValue = node.getNodeValue(); for (int i = 0; i < namedNodeMap.getLength(); i++) {
if (nodeName != null && nodeName.startsWith("xmlns") Node node = namedNodeMap.item(i);
&& (nodeValue == null || nodeValue.length() == 0)) { String nodeName = node.getNodeName();
w3cDocument.getDocumentElement().removeAttribute(nodeName); String nodeValue = node.getNodeValue();
if (nodeName != null && nodeName.startsWith("xmlns")
&& (nodeValue == null || nodeValue.length() == 0)) {
w3cDocument.getDocumentElement().removeAttribute(nodeName);
}
} }
} }
xmlDocument.load(builder.build(w3cDocument)); xmlDocument.load(builder.build(w3cDocument));
@ -1149,77 +1154,80 @@ public class ExchangeSession {
} }
} }
// get inline images from htmlBody (without OWA transformation) // HTML body may be empty
ByteArrayInputStream bais = new ByteArrayInputStream(htmlBody if (htmlBody != null && htmlBody.length() > 0) {
// quick fix remove default office namespace // get inline images from htmlBody (without OWA transformation)
.replaceFirst("xmlns=\".*\"", "") ByteArrayInputStream bais = new ByteArrayInputStream(htmlBody
// quick fix remove inline processing instructions // quick fix remove default office namespace
.replaceAll("<\\?xml:namespace", "") .replaceFirst("xmlns=\".*\"", "")
.getBytes("UTF-8")); // quick fix remove inline processing instructions
XmlDocument xmlBody = tidyDocument(bais); .replaceAll("<\\?xml:namespace", "")
List<Attribute> htmlBodyAllImgList = xmlBody.getNodes("//img/@src"); .getBytes("UTF-8"));
// remove absolute images from body img list XmlDocument xmlBody = tidyDocument(bais);
List<String> htmlBodyImgList = new ArrayList<String>(); List<Attribute> htmlBodyAllImgList = xmlBody.getNodes("//img/@src");
for (Attribute imgAttribute : htmlBodyAllImgList) { // remove absolute images from body img list
String value = imgAttribute.getValue(); List<String> htmlBodyImgList = new ArrayList<String>();
if (!value.startsWith("http://") && !value.startsWith("https://")) { for (Attribute imgAttribute : htmlBodyAllImgList) {
htmlBodyImgList.add(value); String value = imgAttribute.getValue();
if (!value.startsWith("http://") && !value.startsWith("https://")) {
htmlBodyImgList.add(value);
}
} }
}
// set inline attachments flag // set inline attachments flag
hasInlineAttachment = (htmlBodyImgList.size() > 0); hasInlineAttachment = (htmlBodyImgList.size() > 0);
// use owa generated body to look for inline images // use owa generated body to look for inline images
List<Attribute> imgList = xmlDocument.getNodes("//img/@src"); List<Attribute> imgList = xmlDocument.getNodes("//img/@src");
// TODO : add body background, does not work in thunderbird // TODO : add body background, does not work in thunderbird
// htmlBodyImgList.addAll(xmlBody.getNodes("//body/@background")); // htmlBodyImgList.addAll(xmlBody.getNodes("//body/@background"));
// imgList.addAll(xmlDocument.getNodes("//td/@background")); // imgList.addAll(xmlDocument.getNodes("//td/@background"));
int inlineImageCount = 0; int inlineImageCount = 0;
for (Attribute element : imgList) { for (Attribute element : imgList) {
String attachmentHref = element.getValue(); String attachmentHref = element.getValue();
// filter external images // filter external images
if (attachmentHref.startsWith("1_multipart")) { if (attachmentHref.startsWith("1_multipart")) {
attachmentHref = URIUtil.decode(attachmentHref); attachmentHref = URIUtil.decode(attachmentHref);
if (attachmentHref.endsWith("?Security=3")) { if (attachmentHref.endsWith("?Security=3")) {
attachmentHref = attachmentHref.substring(0, attachmentHref.indexOf('?')); attachmentHref = attachmentHref.substring(0, attachmentHref.indexOf('?'));
} }
String attachmentName = attachmentHref.substring(attachmentHref.lastIndexOf('/') + 1); String attachmentName = attachmentHref.substring(attachmentHref.lastIndexOf('/') + 1);
// handle strange cases // handle strange cases
if (attachmentName.charAt(1) == '_') { if (attachmentName.charAt(1) == '_') {
attachmentName = attachmentName.substring(2); attachmentName = attachmentName.substring(2);
} }
if (attachmentName.startsWith("%31_multipart%3F2_")) { if (attachmentName.startsWith("%31_multipart%3F2_")) {
attachmentName = attachmentName.substring(18); attachmentName = attachmentName.substring(18);
} }
// decode slashes // decode slashes
attachmentName = attachmentName.replaceAll("_xF8FF_", "/"); attachmentName = attachmentName.replaceAll("_xF8FF_", "/");
// exclude inline external images // exclude inline external images
if (!attachmentName.startsWith("http://") && !attachmentName.startsWith("https://")) { if (!attachmentName.startsWith("http://") && !attachmentName.startsWith("https://")) {
Attachment attachment = new Attachment(); Attachment attachment = new Attachment();
attachment.name = attachmentName; attachment.name = attachmentName;
attachment.href = messageUrl + "/" + attachmentHref; attachment.href = messageUrl + "/" + attachmentHref;
if (htmlBodyImgList.size() > inlineImageCount) { if (htmlBodyImgList.size() > inlineImageCount) {
String contentid = htmlBodyImgList.get(inlineImageCount++); String contentid = htmlBodyImgList.get(inlineImageCount++);
if (contentid.startsWith("cid:")) { if (contentid.startsWith("cid:")) {
attachment.contentid = contentid.substring("cid:".length()); attachment.contentid = contentid.substring("cid:".length());
} else {
attachment.contentid = contentid;
// must patch htmlBody for inline image without cid
htmlBody = htmlBody.replaceFirst(attachment.contentid, "cid:" + attachment.contentid);
}
} else { } else {
attachment.contentid = contentid; logger.warn("More images in OWA body !");
// must patch htmlBody for inline image without cid
htmlBody = htmlBody.replaceFirst(attachment.contentid, "cid:" + attachment.contentid);
} }
} else { // add only inline images
logger.warn("More images in OWA body !"); if (attachment.contentid != null) {
attachmentsMap.put(attachmentName, attachment);
}
logger.debug("Inline image attachment ID:" + attachment.contentid
+ " name: " + attachment.name + " href: " + attachment.href);
} }
// add only inline images
if (attachment.contentid != null) {
attachmentsMap.put(attachmentName, attachment);
}
logger.debug("Inline image attachment ID:" + attachment.contentid
+ " name: " + attachment.name + " href: " + attachment.href);
} }
} }
} }
@ -1314,19 +1322,19 @@ public class ExchangeSession {
int equalsIndex = token.indexOf('='); int equalsIndex = token.indexOf('=');
if (equalsIndex > 0) { if (equalsIndex > 0) {
String tokenName = token.substring(0, equalsIndex); String tokenName = token.substring(0, equalsIndex);
if ("charset".equals(tokenName)) { if ("charset".equalsIgnoreCase(tokenName)) {
charset = token.substring(equalsIndex + 1); charset = token.substring(equalsIndex + 1);
if (charset.startsWith("\"")) { if (charset.startsWith("\"")) {
charset = charset.substring(1, charset.lastIndexOf("\"")); charset = charset.substring(1, charset.lastIndexOf("\""));
} }
} else if ("name".equals(tokenName.toLowerCase())) { } else if ("name".equalsIgnoreCase(tokenName.toLowerCase())) {
name = token.substring(equalsIndex + 1); name = token.substring(equalsIndex + 1);
if (name.startsWith("\"")) { if (name.startsWith("\"")) {
name = name.substring(1, name.lastIndexOf("\"")); name = name.substring(1, name.lastIndexOf("\""));
} }
// name can be mime encoded // name can be mime encoded
name = MimeUtility.decodeText(name); name = MimeUtility.decodeText(name);
} else if ("boundary".equals(tokenName)) { } else if ("boundary".equalsIgnoreCase(tokenName)) {
boundary = token.substring(equalsIndex + 1); boundary = token.substring(equalsIndex + 1);
if (boundary.startsWith("\"")) { if (boundary.startsWith("\"")) {
boundary = boundary.substring(1, boundary.lastIndexOf("\"")); boundary = boundary.substring(1, boundary.lastIndexOf("\""));