Added TNEF decoder

This commit is contained in:
M66B 2020-10-17 21:05:37 +02:00
parent cf0a2582df
commit 800ba51cc2
4 changed files with 92 additions and 0 deletions

View File

@ -28,3 +28,4 @@ FairEmail uses:
* [Disconnect's tracker protection lists](https://github.com/disconnectme/disconnect-tracking-protection). Copyright 2010-2020 Disconnect, Inc. [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International license](https://github.com/disconnectme/disconnect-tracking-protection/blob/master/LICENSE).
* [Over-Scroll Support For Android's RecyclerView, ListView, GridView, ScrollView ...](https://github.com/EverythingMe/overscroll-decor). Copyright (c) 2015, DoAT Media Ltd. [BSD-2-Clause License](https://github.com/EverythingMe/overscroll-decor/blob/master/LICENSE)
* [Compact Encoding Detection](https://github.com/google/compact_enc_det). Copyright 2016 Google Inc. [Apache License 2.0](https://github.com/google/compact_enc_det/blob/master/LICENSE).
* [POI-HMEF](https://poi.apache.org/components/hmef/index.html). Copyright © 2001-2020 The Apache Software Foundation. [Apache Software License v2](https://poi.apache.org/devel/guidelines.html#The+Licensing).

View File

@ -276,6 +276,7 @@ dependencies {
def overscroll_version = "1.1.0"
def appauth_version = "0.7.1"
def jcharset_version = "2.1"
def apache_poi = "4.1.2"
// https://developer.android.com/jetpack/androidx/releases/
@ -436,4 +437,8 @@ dependencies {
// http://www.freeutils.net/source/jcharset/
// https://mvnrepository.com/artifact/net.freeutils/jcharset
implementation "net.freeutils:jcharset:$jcharset_version"
// https://poi.apache.org/components/hmef/index.html
// https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad
implementation "org.apache.poi:poi-scratchpad:$apache_poi"
}

View File

@ -28,3 +28,4 @@ FairEmail uses:
* [Disconnect's tracker protection lists](https://github.com/disconnectme/disconnect-tracking-protection). Copyright 2010-2020 Disconnect, Inc. [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International license](https://github.com/disconnectme/disconnect-tracking-protection/blob/master/LICENSE).
* [Over-Scroll Support For Android's RecyclerView, ListView, GridView, ScrollView ...](https://github.com/EverythingMe/overscroll-decor). Copyright (c) 2015, DoAT Media Ltd. [BSD-2-Clause License](https://github.com/EverythingMe/overscroll-decor/blob/master/LICENSE)
* [Compact Encoding Detection](https://github.com/google/compact_enc_det). Copyright 2016 Google Inc. [Apache License 2.0](https://github.com/google/compact_enc_det/blob/master/LICENSE).
* [POI-HMEF](https://poi.apache.org/components/hmef/index.html). Copyright © 2001-2020 The Apache Software Foundation. [Apache Software License v2](https://poi.apache.org/devel/guidelines.html#The+Licensing).

View File

@ -1940,6 +1940,10 @@ public class MessageHelper {
throw new IllegalArgumentException("Attachment not found");
downloadAttachment(context, index, local);
if (Helper.isTnef(local.type) ||
("application/octet-stream".equals(local.type) && "winmail.dat".equals(local.name)))
decodeTNEF(context, local);
}
void downloadAttachment(Context context, int index, EntityAttachment local) throws MessagingException, IOException {
@ -2058,6 +2062,87 @@ public class MessageHelper {
}
}
private void decodeTNEF(Context context, EntityAttachment local) {
try {
DB db = DB.getInstance(context);
int subsequence = 0;
// https://poi.apache.org/components/hmef/index.html
File file = local.getFile(context);
org.apache.poi.hmef.HMEFMessage msg = new org.apache.poi.hmef.HMEFMessage(new FileInputStream(file));
String subject = msg.getSubject();
if (!TextUtils.isEmpty(subject)) {
EntityAttachment attachment = new EntityAttachment();
attachment.message = local.message;
attachment.sequence = local.sequence;
attachment.subsequence = ++subsequence;
attachment.name = "subject.txt";
attachment.type = "text/plain";
attachment.disposition = Part.ATTACHMENT;
attachment.id = db.attachment().insertAttachment(attachment);
Helper.writeText(attachment.getFile(context), subject);
db.attachment().setDownloaded(attachment.id, (long) subject.length());
}
String body = msg.getBody();
if (!TextUtils.isEmpty(body)) {
EntityAttachment attachment = new EntityAttachment();
attachment.message = local.message;
attachment.sequence = local.sequence;
attachment.subsequence = ++subsequence;
attachment.name = "document.rtf";
attachment.type = "application/rtf";
attachment.disposition = Part.ATTACHMENT;
attachment.id = db.attachment().insertAttachment(attachment);
Helper.writeText(attachment.getFile(context), body);
db.attachment().setDownloaded(attachment.id, (long) body.length());
}
for (org.apache.poi.hmef.Attachment at : msg.getAttachments()) {
EntityAttachment attachment = new EntityAttachment();
attachment.message = local.message;
attachment.sequence = local.sequence;
attachment.subsequence = ++subsequence;
attachment.name = at.getLongFilename();
attachment.type = Helper.guessMimeType(attachment.name);
attachment.disposition = Part.ATTACHMENT;
attachment.id = db.attachment().insertAttachment(attachment);
byte[] data = at.getContents();
try (OutputStream os = new FileOutputStream(attachment.getFile(context))) {
os.write(data);
}
db.attachment().setDownloaded(attachment.id, (long) data.length);
}
StringBuilder sb = new StringBuilder();
for (org.apache.poi.hmef.attribute.TNEFAttribute attr : msg.getMessageAttributes())
sb.append(attr.toString()).append("\r\n");
for (org.apache.poi.hmef.attribute.MAPIAttribute attr : msg.getMessageMAPIAttributes())
if (!org.apache.poi.hsmf.datatypes.MAPIProperty.RTF_COMPRESSED.equals(attr.getProperty()))
sb.append(attr.toString()).append("\r\n");
if (sb.length() > 0) {
EntityAttachment attachment = new EntityAttachment();
attachment.message = local.message;
attachment.sequence = local.sequence;
attachment.subsequence = ++subsequence;
attachment.name = "attributes.txt";
attachment.type = "text/plain";
attachment.disposition = Part.ATTACHMENT;
attachment.id = db.attachment().insertAttachment(attachment);
Helper.writeText(attachment.getFile(context), sb.toString());
db.attachment().setDownloaded(attachment.id, (long) sb.length());
}
} catch (Throwable ex) {
Log.w(ex);
}
}
String getWarnings(String existing) {
if (existing != null)
warnings.add(0, existing);