summaryrefslogtreecommitdiffstats
path: root/emailcommon/src/com/android/emailcommon/internet
diff options
context:
space:
mode:
authorAndrew Sapperstein <asapperstein@google.com>2013-05-31 16:25:02 -0700
committerAndrew Sapperstein <asapperstein@google.com>2013-05-31 16:28:51 -0700
commit91973256c283ebc409398bf2cfd747b978bb7b03 (patch)
tree5fc93419f55a7a704e65b3c7f91cbe8ea4844dfc /emailcommon/src/com/android/emailcommon/internet
parentf5ed3d2c9d768b053cf218f3ebb70bf239974f0a (diff)
downloadandroid_packages_apps_Email-91973256c283ebc409398bf2cfd747b978bb7b03.tar.gz
android_packages_apps_Email-91973256c283ebc409398bf2cfd747b978bb7b03.tar.bz2
android_packages_apps_Email-91973256c283ebc409398bf2cfd747b978bb7b03.zip
Moved code out of emailcommon to UnifedEmail.
This CL is mostly just deletion since the new code is in a new project. Change-Id: I4aee519187a6ed7514c97d2a7a85ed29ea29d25f
Diffstat (limited to 'emailcommon/src/com/android/emailcommon/internet')
-rw-r--r--emailcommon/src/com/android/emailcommon/internet/BinaryTempFileBody.java89
-rw-r--r--emailcommon/src/com/android/emailcommon/internet/MimeBodyPart.java193
-rw-r--r--emailcommon/src/com/android/emailcommon/internet/MimeHeader.java153
-rw-r--r--emailcommon/src/com/android/emailcommon/internet/MimeMessage.java644
-rw-r--r--emailcommon/src/com/android/emailcommon/internet/MimeMultipart.java111
-rw-r--r--emailcommon/src/com/android/emailcommon/internet/MimeUtility.java453
-rw-r--r--emailcommon/src/com/android/emailcommon/internet/TextBody.java62
7 files changed, 0 insertions, 1705 deletions
diff --git a/emailcommon/src/com/android/emailcommon/internet/BinaryTempFileBody.java b/emailcommon/src/com/android/emailcommon/internet/BinaryTempFileBody.java
deleted file mode 100644
index f0821edd4..000000000
--- a/emailcommon/src/com/android/emailcommon/internet/BinaryTempFileBody.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed 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 com.android.emailcommon.internet;
-
-import com.android.emailcommon.TempDirectory;
-import com.android.emailcommon.mail.Body;
-import com.android.emailcommon.mail.MessagingException;
-
-import org.apache.commons.io.IOUtils;
-
-import android.util.Base64;
-import android.util.Base64OutputStream;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * A Body that is backed by a temp file. The Body exposes a getOutputStream method that allows
- * the user to write to the temp file. After the write the body is available via getInputStream
- * and writeTo one time. After writeTo is called, or the InputStream returned from
- * getInputStream is closed the file is deleted and the Body should be considered disposed of.
- */
-public class BinaryTempFileBody implements Body {
- private File mFile;
-
- /**
- * An alternate way to put data into a BinaryTempFileBody is to simply supply an already-
- * created file. Note that this file will be deleted after it is read.
- * @param filePath The file containing the data to be stored on disk temporarily
- */
- public void setFile(String filePath) {
- mFile = new File(filePath);
- }
-
- public OutputStream getOutputStream() throws IOException {
- mFile = File.createTempFile("body", null, TempDirectory.getTempDirectory());
- mFile.deleteOnExit();
- return new FileOutputStream(mFile);
- }
-
- public InputStream getInputStream() throws MessagingException {
- try {
- return new BinaryTempFileBodyInputStream(new FileInputStream(mFile));
- }
- catch (IOException ioe) {
- throw new MessagingException("Unable to open body", ioe);
- }
- }
-
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- InputStream in = getInputStream();
- Base64OutputStream base64Out = new Base64OutputStream(
- out, Base64.CRLF | Base64.NO_CLOSE);
- IOUtils.copy(in, base64Out);
- base64Out.close();
- mFile.delete();
- }
-
- class BinaryTempFileBodyInputStream extends FilterInputStream {
- public BinaryTempFileBodyInputStream(InputStream in) {
- super(in);
- }
-
- @Override
- public void close() throws IOException {
- super.close();
- mFile.delete();
- }
- }
-}
diff --git a/emailcommon/src/com/android/emailcommon/internet/MimeBodyPart.java b/emailcommon/src/com/android/emailcommon/internet/MimeBodyPart.java
deleted file mode 100644
index 01efd554f..000000000
--- a/emailcommon/src/com/android/emailcommon/internet/MimeBodyPart.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed 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 com.android.emailcommon.internet;
-
-import com.android.emailcommon.mail.Body;
-import com.android.emailcommon.mail.BodyPart;
-import com.android.emailcommon.mail.MessagingException;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.regex.Pattern;
-
-/**
- * TODO this is a close approximation of Message, need to update along with
- * Message.
- */
-public class MimeBodyPart extends BodyPart {
- protected MimeHeader mHeader = new MimeHeader();
- protected MimeHeader mExtendedHeader;
- protected Body mBody;
- protected int mSize;
-
- // regex that matches content id surrounded by "<>" optionally.
- private static final Pattern REMOVE_OPTIONAL_BRACKETS = Pattern.compile("^<?([^>]+)>?$");
- // regex that matches end of line.
- private static final Pattern END_OF_LINE = Pattern.compile("\r?\n");
-
- public MimeBodyPart() throws MessagingException {
- this(null);
- }
-
- public MimeBodyPart(Body body) throws MessagingException {
- this(body, null);
- }
-
- public MimeBodyPart(Body body, String mimeType) throws MessagingException {
- if (mimeType != null) {
- setHeader(MimeHeader.HEADER_CONTENT_TYPE, mimeType);
- }
- setBody(body);
- }
-
- protected String getFirstHeader(String name) throws MessagingException {
- return mHeader.getFirstHeader(name);
- }
-
- public void addHeader(String name, String value) throws MessagingException {
- mHeader.addHeader(name, value);
- }
-
- public void setHeader(String name, String value) throws MessagingException {
- mHeader.setHeader(name, value);
- }
-
- public String[] getHeader(String name) throws MessagingException {
- return mHeader.getHeader(name);
- }
-
- public void removeHeader(String name) throws MessagingException {
- mHeader.removeHeader(name);
- }
-
- public Body getBody() throws MessagingException {
- return mBody;
- }
-
- public void setBody(Body body) throws MessagingException {
- this.mBody = body;
- if (body instanceof com.android.emailcommon.mail.Multipart) {
- com.android.emailcommon.mail.Multipart multipart =
- ((com.android.emailcommon.mail.Multipart)body);
- multipart.setParent(this);
- setHeader(MimeHeader.HEADER_CONTENT_TYPE, multipart.getContentType());
- }
- else if (body instanceof TextBody) {
- String contentType = String.format("%s;\n charset=utf-8", getMimeType());
- String name = MimeUtility.getHeaderParameter(getContentType(), "name");
- if (name != null) {
- contentType += String.format(";\n name=\"%s\"", name);
- }
- setHeader(MimeHeader.HEADER_CONTENT_TYPE, contentType);
- setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
- }
- }
-
- public String getContentType() throws MessagingException {
- String contentType = getFirstHeader(MimeHeader.HEADER_CONTENT_TYPE);
- if (contentType == null) {
- return "text/plain";
- } else {
- return contentType;
- }
- }
-
- public String getDisposition() throws MessagingException {
- String contentDisposition = getFirstHeader(MimeHeader.HEADER_CONTENT_DISPOSITION);
- if (contentDisposition == null) {
- return null;
- } else {
- return contentDisposition;
- }
- }
-
- public String getContentId() throws MessagingException {
- String contentId = getFirstHeader(MimeHeader.HEADER_CONTENT_ID);
- if (contentId == null) {
- return null;
- } else {
- // remove optionally surrounding brackets.
- return REMOVE_OPTIONAL_BRACKETS.matcher(contentId).replaceAll("$1");
- }
- }
-
- public String getMimeType() throws MessagingException {
- return MimeUtility.getHeaderParameter(getContentType(), null);
- }
-
- public boolean isMimeType(String mimeType) throws MessagingException {
- return getMimeType().equals(mimeType);
- }
-
- public void setSize(int size) {
- this.mSize = size;
- }
-
- public int getSize() throws MessagingException {
- return mSize;
- }
-
- /**
- * Set extended header
- *
- * @param name Extended header name
- * @param value header value - flattened by removing CR-NL if any
- * remove header if value is null
- * @throws MessagingException
- */
- public void setExtendedHeader(String name, String value) throws MessagingException {
- if (value == null) {
- if (mExtendedHeader != null) {
- mExtendedHeader.removeHeader(name);
- }
- return;
- }
- if (mExtendedHeader == null) {
- mExtendedHeader = new MimeHeader();
- }
- mExtendedHeader.setHeader(name, END_OF_LINE.matcher(value).replaceAll(""));
- }
-
- /**
- * Get extended header
- *
- * @param name Extended header name
- * @return header value - null if header does not exist
- * @throws MessagingException
- */
- public String getExtendedHeader(String name) throws MessagingException {
- if (mExtendedHeader == null) {
- return null;
- }
- return mExtendedHeader.getFirstHeader(name);
- }
-
- /**
- * Write the MimeMessage out in MIME format.
- */
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
- mHeader.writeTo(out);
- writer.write("\r\n");
- writer.flush();
- if (mBody != null) {
- mBody.writeTo(out);
- }
- }
-}
diff --git a/emailcommon/src/com/android/emailcommon/internet/MimeHeader.java b/emailcommon/src/com/android/emailcommon/internet/MimeHeader.java
deleted file mode 100644
index b0ad7772e..000000000
--- a/emailcommon/src/com/android/emailcommon/internet/MimeHeader.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed 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 com.android.emailcommon.internet;
-
-import com.android.emailcommon.mail.MessagingException;
-import com.android.emailcommon.utility.Utility;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-
-public class MimeHeader {
- /**
- * Application specific header that contains Store specific information about an attachment.
- * In IMAP this contains the IMAP BODYSTRUCTURE part id so that the ImapStore can later
- * retrieve the attachment at will from the server.
- * The info is recorded from this header on LocalStore.appendMessages and is put back
- * into the MIME data by LocalStore.fetch.
- */
- public static final String HEADER_ANDROID_ATTACHMENT_STORE_DATA = "X-Android-Attachment-StoreData";
- /**
- * Application specific header that is used to tag body parts for quoted/forwarded messages.
- */
- public static final String HEADER_ANDROID_BODY_QUOTED_PART = "X-Android-Body-Quoted-Part";
-
- public static final String HEADER_CONTENT_TYPE = "Content-Type";
- public static final String HEADER_CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
- public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
- public static final String HEADER_CONTENT_ID = "Content-ID";
-
- /**
- * Fields that should be omitted when writing the header using writeTo()
- */
- private static final String[] WRITE_OMIT_FIELDS = {
-// HEADER_ANDROID_ATTACHMENT_DOWNLOADED,
-// HEADER_ANDROID_ATTACHMENT_ID,
- HEADER_ANDROID_ATTACHMENT_STORE_DATA
- };
-
- protected final ArrayList<Field> mFields = new ArrayList<Field>();
-
- public void clear() {
- mFields.clear();
- }
-
- public String getFirstHeader(String name) throws MessagingException {
- String[] header = getHeader(name);
- if (header == null) {
- return null;
- }
- return header[0];
- }
-
- public void addHeader(String name, String value) throws MessagingException {
- mFields.add(new Field(name, value));
- }
-
- public void setHeader(String name, String value) throws MessagingException {
- if (name == null || value == null) {
- return;
- }
- removeHeader(name);
- addHeader(name, value);
- }
-
- public String[] getHeader(String name) throws MessagingException {
- ArrayList<String> values = new ArrayList<String>();
- for (Field field : mFields) {
- if (field.name.equalsIgnoreCase(name)) {
- values.add(field.value);
- }
- }
- if (values.size() == 0) {
- return null;
- }
- return values.toArray(new String[] {});
- }
-
- public void removeHeader(String name) throws MessagingException {
- ArrayList<Field> removeFields = new ArrayList<Field>();
- for (Field field : mFields) {
- if (field.name.equalsIgnoreCase(name)) {
- removeFields.add(field);
- }
- }
- mFields.removeAll(removeFields);
- }
-
- /**
- * Write header into String
- *
- * @return CR-NL separated header string except the headers in writeOmitFields
- * null if header is empty
- */
- public String writeToString() {
- if (mFields.size() == 0) {
- return null;
- }
- StringBuilder builder = new StringBuilder();
- for (Field field : mFields) {
- if (!Utility.arrayContains(WRITE_OMIT_FIELDS, field.name)) {
- builder.append(field.name + ": " + field.value + "\r\n");
- }
- }
- return builder.toString();
- }
-
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
- for (Field field : mFields) {
- if (!Utility.arrayContains(WRITE_OMIT_FIELDS, field.name)) {
- writer.write(field.name + ": " + field.value + "\r\n");
- }
- }
- writer.flush();
- }
-
- private static class Field {
- final String name;
- final String value;
-
- public Field(String name, String value) {
- this.name = name;
- this.value = value;
- }
-
- @Override
- public String toString() {
- return name + "=" + value;
- }
- }
-
- @Override
- public String toString() {
- return (mFields == null) ? null : mFields.toString();
- }
-}
diff --git a/emailcommon/src/com/android/emailcommon/internet/MimeMessage.java b/emailcommon/src/com/android/emailcommon/internet/MimeMessage.java
deleted file mode 100644
index b3ee70ee4..000000000
--- a/emailcommon/src/com/android/emailcommon/internet/MimeMessage.java
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed 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 com.android.emailcommon.internet;
-
-import com.android.emailcommon.mail.Address;
-import com.android.emailcommon.mail.Body;
-import com.android.emailcommon.mail.BodyPart;
-import com.android.emailcommon.mail.Message;
-import com.android.emailcommon.mail.MessagingException;
-import com.android.emailcommon.mail.Multipart;
-import com.android.emailcommon.mail.Part;
-
-import org.apache.james.mime4j.BodyDescriptor;
-import org.apache.james.mime4j.ContentHandler;
-import org.apache.james.mime4j.EOLConvertingInputStream;
-import org.apache.james.mime4j.MimeStreamParser;
-import org.apache.james.mime4j.field.DateTimeField;
-import org.apache.james.mime4j.field.Field;
-
-import android.text.TextUtils;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Stack;
-import java.util.regex.Pattern;
-
-/**
- * An implementation of Message that stores all of its metadata in RFC 822 and
- * RFC 2045 style headers.
- *
- * NOTE: Automatic generation of a local message-id is becoming unwieldy and should be removed.
- * It would be better to simply do it explicitly on local creation of new outgoing messages.
- */
-public class MimeMessage extends Message {
- private MimeHeader mHeader;
- private MimeHeader mExtendedHeader;
-
- // NOTE: The fields here are transcribed out of headers, and values stored here will supercede
- // the values found in the headers. Use caution to prevent any out-of-phase errors. In
- // particular, any adds/changes/deletes here must be echoed by changes in the parse() function.
- private Address[] mFrom;
- private Address[] mTo;
- private Address[] mCc;
- private Address[] mBcc;
- private Address[] mReplyTo;
- private Date mSentDate;
- private Body mBody;
- protected int mSize;
- private boolean mInhibitLocalMessageId = false;
- private boolean mComplete = true;
-
- // Shared random source for generating local message-id values
- private static final java.util.Random sRandom = new java.util.Random();
-
- // In MIME, en_US-like date format should be used. In other words "MMM" should be encoded to
- // "Jan", not the other localized format like "Ene" (meaning January in locale es).
- // This conversion is used when generating outgoing MIME messages. Incoming MIME date
- // headers are parsed by org.apache.james.mime4j.field.DateTimeField which does not have any
- // localization code.
- private static final SimpleDateFormat DATE_FORMAT =
- new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
-
- // regex that matches content id surrounded by "<>" optionally.
- private static final Pattern REMOVE_OPTIONAL_BRACKETS = Pattern.compile("^<?([^>]+)>?$");
- // regex that matches end of line.
- private static final Pattern END_OF_LINE = Pattern.compile("\r?\n");
-
- public MimeMessage() {
- mHeader = null;
- }
-
- /**
- * Generate a local message id. This is only used when none has been assigned, and is
- * installed lazily. Any remote (typically server-assigned) message id takes precedence.
- * @return a long, locally-generated message-ID value
- */
- private String generateMessageId() {
- StringBuffer sb = new StringBuffer();
- sb.append("<");
- for (int i = 0; i < 24; i++) {
- // We'll use a 5-bit range (0..31)
- int value = sRandom.nextInt() & 31;
- char c = "0123456789abcdefghijklmnopqrstuv".charAt(value);
- sb.append(c);
- }
- sb.append(".");
- sb.append(Long.toString(System.currentTimeMillis()));
- sb.append("@email.android.com>");
- return sb.toString();
- }
-
- /**
- * Parse the given InputStream using Apache Mime4J to build a MimeMessage.
- *
- * @param in
- * @throws IOException
- * @throws MessagingException
- */
- public MimeMessage(InputStream in) throws IOException, MessagingException {
- parse(in);
- }
-
- private MimeStreamParser init() {
- // Before parsing the input stream, clear all local fields that may be superceded by
- // the new incoming message.
- getMimeHeaders().clear();
- mInhibitLocalMessageId = true;
- mFrom = null;
- mTo = null;
- mCc = null;
- mBcc = null;
- mReplyTo = null;
- mSentDate = null;
- mBody = null;
-
- MimeStreamParser parser = new MimeStreamParser();
- parser.setContentHandler(new MimeMessageBuilder());
- return parser;
- }
-
- protected void parse(InputStream in) throws IOException, MessagingException {
- MimeStreamParser parser = init();
- parser.parse(new EOLConvertingInputStream(in));
- mComplete = !parser.getPrematureEof();
- }
-
- public void parse(InputStream in, EOLConvertingInputStream.Callback callback)
- throws IOException, MessagingException {
- MimeStreamParser parser = init();
- parser.parse(new EOLConvertingInputStream(in, getSize(), callback));
- mComplete = !parser.getPrematureEof();
- }
-
- /**
- * Return the internal mHeader value, with very lazy initialization.
- * The goal is to save memory by not creating the headers until needed.
- */
- private MimeHeader getMimeHeaders() {
- if (mHeader == null) {
- mHeader = new MimeHeader();
- }
- return mHeader;
- }
-
- @Override
- public Date getReceivedDate() throws MessagingException {
- return null;
- }
-
- @Override
- public Date getSentDate() throws MessagingException {
- if (mSentDate == null) {
- try {
- DateTimeField field = (DateTimeField)Field.parse("Date: "
- + MimeUtility.unfoldAndDecode(getFirstHeader("Date")));
- mSentDate = field.getDate();
- } catch (Exception e) {
-
- }
- }
- return mSentDate;
- }
-
- @Override
- public void setSentDate(Date sentDate) throws MessagingException {
- setHeader("Date", DATE_FORMAT.format(sentDate));
- this.mSentDate = sentDate;
- }
-
- @Override
- public String getContentType() throws MessagingException {
- String contentType = getFirstHeader(MimeHeader.HEADER_CONTENT_TYPE);
- if (contentType == null) {
- return "text/plain";
- } else {
- return contentType;
- }
- }
-
- public String getDisposition() throws MessagingException {
- String contentDisposition = getFirstHeader(MimeHeader.HEADER_CONTENT_DISPOSITION);
- if (contentDisposition == null) {
- return null;
- } else {
- return contentDisposition;
- }
- }
-
- public String getContentId() throws MessagingException {
- String contentId = getFirstHeader(MimeHeader.HEADER_CONTENT_ID);
- if (contentId == null) {
- return null;
- } else {
- // remove optionally surrounding brackets.
- return REMOVE_OPTIONAL_BRACKETS.matcher(contentId).replaceAll("$1");
- }
- }
-
- public boolean isComplete() {
- return mComplete;
- }
-
- public String getMimeType() throws MessagingException {
- return MimeUtility.getHeaderParameter(getContentType(), null);
- }
-
- public int getSize() throws MessagingException {
- return mSize;
- }
-
- /**
- * Returns a list of the given recipient type from this message. If no addresses are
- * found the method returns an empty array.
- */
- @Override
- public Address[] getRecipients(RecipientType type) throws MessagingException {
- if (type == RecipientType.TO) {
- if (mTo == null) {
- mTo = Address.parse(MimeUtility.unfold(getFirstHeader("To")));
- }
- return mTo;
- } else if (type == RecipientType.CC) {
- if (mCc == null) {
- mCc = Address.parse(MimeUtility.unfold(getFirstHeader("CC")));
- }
- return mCc;
- } else if (type == RecipientType.BCC) {
- if (mBcc == null) {
- mBcc = Address.parse(MimeUtility.unfold(getFirstHeader("BCC")));
- }
- return mBcc;
- } else {
- throw new MessagingException("Unrecognized recipient type.");
- }
- }
-
- @Override
- public void setRecipients(RecipientType type, Address[] addresses) throws MessagingException {
- final int TO_LENGTH = 4; // "To: "
- final int CC_LENGTH = 4; // "Cc: "
- final int BCC_LENGTH = 5; // "Bcc: "
- if (type == RecipientType.TO) {
- if (addresses == null || addresses.length == 0) {
- removeHeader("To");
- this.mTo = null;
- } else {
- setHeader("To", MimeUtility.fold(Address.toHeader(addresses), TO_LENGTH));
- this.mTo = addresses;
- }
- } else if (type == RecipientType.CC) {
- if (addresses == null || addresses.length == 0) {
- removeHeader("CC");
- this.mCc = null;
- } else {
- setHeader("CC", MimeUtility.fold(Address.toHeader(addresses), CC_LENGTH));
- this.mCc = addresses;
- }
- } else if (type == RecipientType.BCC) {
- if (addresses == null || addresses.length == 0) {
- removeHeader("BCC");
- this.mBcc = null;
- } else {
- setHeader("BCC", MimeUtility.fold(Address.toHeader(addresses), BCC_LENGTH));
- this.mBcc = addresses;
- }
- } else {
- throw new MessagingException("Unrecognized recipient type.");
- }
- }
-
- /**
- * Returns the unfolded, decoded value of the Subject header.
- */
- @Override
- public String getSubject() throws MessagingException {
- return MimeUtility.unfoldAndDecode(getFirstHeader("Subject"));
- }
-
- @Override
- public void setSubject(String subject) throws MessagingException {
- final int HEADER_NAME_LENGTH = 9; // "Subject: "
- setHeader("Subject", MimeUtility.foldAndEncode2(subject, HEADER_NAME_LENGTH));
- }
-
- @Override
- public Address[] getFrom() throws MessagingException {
- if (mFrom == null) {
- String list = MimeUtility.unfold(getFirstHeader("From"));
- if (list == null || list.length() == 0) {
- list = MimeUtility.unfold(getFirstHeader("Sender"));
- }
- mFrom = Address.parse(list);
- }
- return mFrom;
- }
-
- @Override
- public void setFrom(Address from) throws MessagingException {
- final int FROM_LENGTH = 6; // "From: "
- if (from != null) {
- setHeader("From", MimeUtility.fold(from.toHeader(), FROM_LENGTH));
- this.mFrom = new Address[] {
- from
- };
- } else {
- this.mFrom = null;
- }
- }
-
- @Override
- public Address[] getReplyTo() throws MessagingException {
- if (mReplyTo == null) {
- mReplyTo = Address.parse(MimeUtility.unfold(getFirstHeader("Reply-to")));
- }
- return mReplyTo;
- }
-
- @Override
- public void setReplyTo(Address[] replyTo) throws MessagingException {
- final int REPLY_TO_LENGTH = 10; // "Reply-to: "
- if (replyTo == null || replyTo.length == 0) {
- removeHeader("Reply-to");
- mReplyTo = null;
- } else {
- setHeader("Reply-to", MimeUtility.fold(Address.toHeader(replyTo), REPLY_TO_LENGTH));
- mReplyTo = replyTo;
- }
- }
-
- /**
- * Set the mime "Message-ID" header
- * @param messageId the new Message-ID value
- * @throws MessagingException
- */
- @Override
- public void setMessageId(String messageId) throws MessagingException {
- setHeader("Message-ID", messageId);
- }
-
- /**
- * Get the mime "Message-ID" header. This value will be preloaded with a locally-generated
- * random ID, if the value has not previously been set. Local generation can be inhibited/
- * overridden by explicitly clearing the headers, removing the message-id header, etc.
- * @return the Message-ID header string, or null if explicitly has been set to null
- */
- @Override
- public String getMessageId() throws MessagingException {
- String messageId = getFirstHeader("Message-ID");
- if (messageId == null && !mInhibitLocalMessageId) {
- messageId = generateMessageId();
- setMessageId(messageId);
- }
- return messageId;
- }
-
- @Override
- public void saveChanges() throws MessagingException {
- throw new MessagingException("saveChanges not yet implemented");
- }
-
- @Override
- public Body getBody() throws MessagingException {
- return mBody;
- }
-
- @Override
- public void setBody(Body body) throws MessagingException {
- this.mBody = body;
- if (body instanceof Multipart) {
- Multipart multipart = ((Multipart)body);
- multipart.setParent(this);
- setHeader(MimeHeader.HEADER_CONTENT_TYPE, multipart.getContentType());
- setHeader("MIME-Version", "1.0");
- }
- else if (body instanceof TextBody) {
- setHeader(MimeHeader.HEADER_CONTENT_TYPE, String.format("%s;\n charset=utf-8",
- getMimeType()));
- setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
- }
- }
-
- protected String getFirstHeader(String name) throws MessagingException {
- return getMimeHeaders().getFirstHeader(name);
- }
-
- @Override
- public void addHeader(String name, String value) throws MessagingException {
- getMimeHeaders().addHeader(name, value);
- }
-
- @Override
- public void setHeader(String name, String value) throws MessagingException {
- getMimeHeaders().setHeader(name, value);
- }
-
- @Override
- public String[] getHeader(String name) throws MessagingException {
- return getMimeHeaders().getHeader(name);
- }
-
- @Override
- public void removeHeader(String name) throws MessagingException {
- getMimeHeaders().removeHeader(name);
- if ("Message-ID".equalsIgnoreCase(name)) {
- mInhibitLocalMessageId = true;
- }
- }
-
- /**
- * Set extended header
- *
- * @param name Extended header name
- * @param value header value - flattened by removing CR-NL if any
- * remove header if value is null
- * @throws MessagingException
- */
- public void setExtendedHeader(String name, String value) throws MessagingException {
- if (value == null) {
- if (mExtendedHeader != null) {
- mExtendedHeader.removeHeader(name);
- }
- return;
- }
- if (mExtendedHeader == null) {
- mExtendedHeader = new MimeHeader();
- }
- mExtendedHeader.setHeader(name, END_OF_LINE.matcher(value).replaceAll(""));
- }
-
- /**
- * Get extended header
- *
- * @param name Extended header name
- * @return header value - null if header does not exist
- * @throws MessagingException
- */
- public String getExtendedHeader(String name) throws MessagingException {
- if (mExtendedHeader == null) {
- return null;
- }
- return mExtendedHeader.getFirstHeader(name);
- }
-
- /**
- * Set entire extended headers from String
- *
- * @param headers Extended header and its value - "CR-NL-separated pairs
- * if null or empty, remove entire extended headers
- * @throws MessagingException
- */
- public void setExtendedHeaders(String headers) throws MessagingException {
- if (TextUtils.isEmpty(headers)) {
- mExtendedHeader = null;
- } else {
- mExtendedHeader = new MimeHeader();
- for (String header : END_OF_LINE.split(headers)) {
- String[] tokens = header.split(":", 2);
- if (tokens.length != 2) {
- throw new MessagingException("Illegal extended headers: " + headers);
- }
- mExtendedHeader.setHeader(tokens[0].trim(), tokens[1].trim());
- }
- }
- }
-
- /**
- * Get entire extended headers as String
- *
- * @return "CR-NL-separated extended headers - null if extended header does not exist
- */
- public String getExtendedHeaders() {
- if (mExtendedHeader != null) {
- return mExtendedHeader.writeToString();
- }
- return null;
- }
-
- /**
- * Write message header and body to output stream
- *
- * @param out Output steam to write message header and body.
- */
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
- // Force creation of local message-id
- getMessageId();
- getMimeHeaders().writeTo(out);
- // mExtendedHeader will not be write out to external output stream,
- // because it is intended to internal use.
- writer.write("\r\n");
- writer.flush();
- if (mBody != null) {
- mBody.writeTo(out);
- }
- }
-
- public InputStream getInputStream() throws MessagingException {
- return null;
- }
-
- class MimeMessageBuilder implements ContentHandler {
- private Stack<Object> stack = new Stack<Object>();
-
- public MimeMessageBuilder() {
- }
-
- private void expect(Class c) {
- if (!c.isInstance(stack.peek())) {
- throw new IllegalStateException("Internal stack error: " + "Expected '"
- + c.getName() + "' found '" + stack.peek().getClass().getName() + "'");
- }
- }
-
- public void startMessage() {
- if (stack.isEmpty()) {
- stack.push(MimeMessage.this);
- } else {
- expect(Part.class);
- try {
- MimeMessage m = new MimeMessage();
- ((Part)stack.peek()).setBody(m);
- stack.push(m);
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
- }
-
- public void endMessage() {
- expect(MimeMessage.class);
- stack.pop();
- }
-
- public void startHeader() {
- expect(Part.class);
- }
-
- public void field(String fieldData) {
- expect(Part.class);
- try {
- String[] tokens = fieldData.split(":", 2);
- ((Part)stack.peek()).addHeader(tokens[0], tokens[1].trim());
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
-
- public void endHeader() {
- expect(Part.class);
- }
-
- public void startMultipart(BodyDescriptor bd) {
- expect(Part.class);
-
- Part e = (Part)stack.peek();
- try {
- MimeMultipart multiPart = new MimeMultipart(e.getContentType());
- e.setBody(multiPart);
- stack.push(multiPart);
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
-
- public void body(BodyDescriptor bd, InputStream in) throws IOException {
- expect(Part.class);
- Body body = MimeUtility.decodeBody(in, bd.getTransferEncoding());
- try {
- ((Part)stack.peek()).setBody(body);
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
-
- public void endMultipart() {
- stack.pop();
- }
-
- public void startBodyPart() {
- expect(MimeMultipart.class);
-
- try {
- MimeBodyPart bodyPart = new MimeBodyPart();
- ((MimeMultipart)stack.peek()).addBodyPart(bodyPart);
- stack.push(bodyPart);
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
-
- public void endBodyPart() {
- expect(BodyPart.class);
- stack.pop();
- }
-
- public void epilogue(InputStream is) throws IOException {
- expect(MimeMultipart.class);
- StringBuffer sb = new StringBuffer();
- int b;
- while ((b = is.read()) != -1) {
- sb.append((char)b);
- }
- // ((Multipart) stack.peek()).setEpilogue(sb.toString());
- }
-
- public void preamble(InputStream is) throws IOException {
- expect(MimeMultipart.class);
- StringBuffer sb = new StringBuffer();
- int b;
- while ((b = is.read()) != -1) {
- sb.append((char)b);
- }
- try {
- ((MimeMultipart)stack.peek()).setPreamble(sb.toString());
- } catch (MessagingException me) {
- throw new Error(me);
- }
- }
-
- public void raw(InputStream is) throws IOException {
- throw new UnsupportedOperationException("Not supported");
- }
- }
-}
diff --git a/emailcommon/src/com/android/emailcommon/internet/MimeMultipart.java b/emailcommon/src/com/android/emailcommon/internet/MimeMultipart.java
deleted file mode 100644
index e6977ee4f..000000000
--- a/emailcommon/src/com/android/emailcommon/internet/MimeMultipart.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed 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 com.android.emailcommon.internet;
-
-import com.android.emailcommon.mail.BodyPart;
-import com.android.emailcommon.mail.MessagingException;
-import com.android.emailcommon.mail.Multipart;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-
-public class MimeMultipart extends Multipart {
- protected String mPreamble;
-
- protected String mContentType;
-
- protected String mBoundary;
-
- protected String mSubType;
-
- public MimeMultipart() throws MessagingException {
- mBoundary = generateBoundary();
- setSubType("mixed");
- }
-
- public MimeMultipart(String contentType) throws MessagingException {
- this.mContentType = contentType;
- try {
- mSubType = MimeUtility.getHeaderParameter(contentType, null).split("/")[1];
- mBoundary = MimeUtility.getHeaderParameter(contentType, "boundary");
- if (mBoundary == null) {
- throw new MessagingException("MultiPart does not contain boundary: " + contentType);
- }
- } catch (Exception e) {
- throw new MessagingException(
- "Invalid MultiPart Content-Type; must contain subtype and boundary. ("
- + contentType + ")", e);
- }
- }
-
- public String generateBoundary() {
- StringBuffer sb = new StringBuffer();
- sb.append("----");
- for (int i = 0; i < 30; i++) {
- sb.append(Integer.toString((int)(Math.random() * 35), 36));
- }
- return sb.toString().toUpperCase();
- }
-
- public String getPreamble() throws MessagingException {
- return mPreamble;
- }
-
- public void setPreamble(String preamble) throws MessagingException {
- this.mPreamble = preamble;
- }
-
- @Override
- public String getContentType() throws MessagingException {
- return mContentType;
- }
-
- public void setSubType(String subType) throws MessagingException {
- this.mSubType = subType;
- mContentType = String.format("multipart/%s; boundary=\"%s\"", subType, mBoundary);
- }
-
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
-
- if (mPreamble != null) {
- writer.write(mPreamble + "\r\n");
- }
-
- for (int i = 0, count = mParts.size(); i < count; i++) {
- BodyPart bodyPart = mParts.get(i);
- writer.write("--" + mBoundary + "\r\n");
- writer.flush();
- bodyPart.writeTo(out);
- writer.write("\r\n");
- }
-
- writer.write("--" + mBoundary + "--\r\n");
- writer.flush();
- }
-
- public InputStream getInputStream() throws MessagingException {
- return null;
- }
-
- public String getSubTypeForTest() {
- return mSubType;
- }
-}
diff --git a/emailcommon/src/com/android/emailcommon/internet/MimeUtility.java b/emailcommon/src/com/android/emailcommon/internet/MimeUtility.java
deleted file mode 100644
index b96e01e59..000000000
--- a/emailcommon/src/com/android/emailcommon/internet/MimeUtility.java
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed 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 com.android.emailcommon.internet;
-
-import android.text.TextUtils;
-import android.util.Base64;
-import android.util.Base64DataException;
-import android.util.Base64InputStream;
-import android.util.Log;
-
-import com.android.emailcommon.Logging;
-import com.android.emailcommon.mail.Body;
-import com.android.emailcommon.mail.BodyPart;
-import com.android.emailcommon.mail.Message;
-import com.android.emailcommon.mail.MessagingException;
-import com.android.emailcommon.mail.Multipart;
-import com.android.emailcommon.mail.Part;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.james.mime4j.codec.EncoderUtil;
-import org.apache.james.mime4j.decoder.DecoderUtil;
-import org.apache.james.mime4j.decoder.QuotedPrintableInputStream;
-import org.apache.james.mime4j.util.CharsetUtil;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class MimeUtility {
-
- public static final String MIME_TYPE_RFC822 = "message/rfc822";
- private final static Pattern PATTERN_CR_OR_LF = Pattern.compile("\r|\n");
-
- /**
- * Replace sequences of CRLF+WSP with WSP. Tries to preserve original string
- * object whenever possible.
- */
- public static String unfold(String s) {
- if (s == null) {
- return null;
- }
- Matcher patternMatcher = PATTERN_CR_OR_LF.matcher(s);
- if (patternMatcher.find()) {
- patternMatcher.reset();
- s = patternMatcher.replaceAll("");
- }
- return s;
- }
-
- public static String decode(String s) {
- if (s == null) {
- return null;
- }
- return DecoderUtil.decodeEncodedWords(s);
- }
-
- public static String unfoldAndDecode(String s) {
- return decode(unfold(s));
- }
-
- // TODO implement proper foldAndEncode
- // NOTE: When this really works, we *must* remove all calls to foldAndEncode2() to prevent
- // duplication of encoding.
- public static String foldAndEncode(String s) {
- return s;
- }
-
- /**
- * INTERIM version of foldAndEncode that will be used only by Subject: headers.
- * This is safer than implementing foldAndEncode() (see above) and risking unknown damage
- * to other headers.
- *
- * TODO: Copy this code to foldAndEncode(), get rid of this function, confirm all working OK.
- *
- * @param s original string to encode and fold
- * @param usedCharacters number of characters already used up by header name
-
- * @return the String ready to be transmitted
- */
- public static String foldAndEncode2(String s, int usedCharacters) {
- // james.mime4j.codec.EncoderUtil.java
- // encode: encodeIfNecessary(text, usage, numUsedInHeaderName)
- // Usage.TEXT_TOKENlooks like the right thing for subjects
- // use WORD_ENTITY for address/names
-
- String encoded = EncoderUtil.encodeIfNecessary(s, EncoderUtil.Usage.TEXT_TOKEN,
- usedCharacters);
-
- return fold(encoded, usedCharacters);
- }
-
- /**
- * INTERIM: From newer version of org.apache.james (but we don't want to import
- * the entire MimeUtil class).
- *
- * Splits the specified string into a multiple-line representation with
- * lines no longer than 76 characters (because the line might contain
- * encoded words; see <a href='http://www.faqs.org/rfcs/rfc2047.html'>RFC
- * 2047</a> section 2). If the string contains non-whitespace sequences
- * longer than 76 characters a line break is inserted at the whitespace
- * character following the sequence resulting in a line longer than 76
- * characters.
- *
- * @param s
- * string to split.
- * @param usedCharacters
- * number of characters already used up. Usually the number of
- * characters for header field name plus colon and one space.
- * @return a multiple-line representation of the given string.
- */
- public static String fold(String s, int usedCharacters) {
- final int maxCharacters = 76;
-
- final int length = s.length();
- if (usedCharacters + length <= maxCharacters)
- return s;
-
- StringBuilder sb = new StringBuilder();
-
- int lastLineBreak = -usedCharacters;
- int wspIdx = indexOfWsp(s, 0);
- while (true) {
- if (wspIdx == length) {
- sb.append(s.substring(Math.max(0, lastLineBreak)));
- return sb.toString();
- }
-
- int nextWspIdx = indexOfWsp(s, wspIdx + 1);
-
- if (nextWspIdx - lastLineBreak > maxCharacters) {
- sb.append(s.substring(Math.max(0, lastLineBreak), wspIdx));
- sb.append("\r\n");
- lastLineBreak = wspIdx;
- }
-
- wspIdx = nextWspIdx;
- }
- }
-
- /**
- * INTERIM: From newer version of org.apache.james (but we don't want to import
- * the entire MimeUtil class).
- *
- * Search for whitespace.
- */
- private static int indexOfWsp(String s, int fromIndex) {
- final int len = s.length();
- for (int index = fromIndex; index < len; index++) {
- char c = s.charAt(index);
- if (c == ' ' || c == '\t')
- return index;
- }
- return len;
- }
-
- /**
- * Returns the named parameter of a header field. If name is null the first
- * parameter is returned, or if there are no additional parameters in the
- * field the entire field is returned. Otherwise the named parameter is
- * searched for in a case insensitive fashion and returned. If the parameter
- * cannot be found the method returns null.
- *
- * TODO: quite inefficient with the inner trimming & splitting.
- * TODO: Also has a latent bug: uses "startsWith" to match the name, which can false-positive.
- * TODO: The doc says that for a null name you get the first param, but you get the header.
- * Should probably just fix the doc, but if other code assumes that behavior, fix the code.
- * TODO: Need to decode %-escaped strings, as in: filename="ab%22d".
- * ('+' -> ' ' conversion too? check RFC)
- *
- * @param header
- * @param name
- * @return the entire header (if name=null), the found parameter, or null
- */
- public static String getHeaderParameter(String header, String name) {
- if (header == null) {
- return null;
- }
- String[] parts = unfold(header).split(";");
- if (name == null) {
- return parts[0].trim();
- }
- String lowerCaseName = name.toLowerCase();
- for (String part : parts) {
- if (part.trim().toLowerCase().startsWith(lowerCaseName)) {
- String[] parameterParts = part.split("=", 2);
- if (parameterParts.length < 2) {
- return null;
- }
- String parameter = parameterParts[1].trim();
- if (parameter.startsWith("\"") && parameter.endsWith("\"")) {
- return parameter.substring(1, parameter.length() - 1);
- } else {
- return parameter;
- }
- }
- }
- return null;
- }
-
- public static Part findFirstPartByMimeType(Part part, String mimeType)
- throws MessagingException {
- if (part.getBody() instanceof Multipart) {
- Multipart multipart = (Multipart)part.getBody();
- for (int i = 0, count = multipart.getCount(); i < count; i++) {
- BodyPart bodyPart = multipart.getBodyPart(i);
- Part ret = findFirstPartByMimeType(bodyPart, mimeType);
- if (ret != null) {
- return ret;
- }
- }
- }
- else if (part.getMimeType().equalsIgnoreCase(mimeType)) {
- return part;
- }
- return null;
- }
-
- public static Part findPartByContentId(Part part, String contentId) throws Exception {
- if (part.getBody() instanceof Multipart) {
- Multipart multipart = (Multipart)part.getBody();
- for (int i = 0, count = multipart.getCount(); i < count; i++) {
- BodyPart bodyPart = multipart.getBodyPart(i);
- Part ret = findPartByContentId(bodyPart, contentId);
- if (ret != null) {
- return ret;
- }
- }
- }
- String cid = part.getContentId();
- if (contentId.equals(cid)) {
- return part;
- }
- return null;
- }
-
- /**
- * Reads the Part's body and returns a String based on any charset conversion that needed
- * to be done.
- * @param part The part containing a body
- * @return a String containing the converted text in the body, or null if there was no text
- * or an error during conversion.
- */
- public static String getTextFromPart(Part part) {
- try {
- if (part != null && part.getBody() != null) {
- InputStream in = part.getBody().getInputStream();
- String mimeType = part.getMimeType();
- if (mimeType != null && MimeUtility.mimeTypeMatches(mimeType, "text/*")) {
- /*
- * Now we read the part into a buffer for further processing. Because
- * the stream is now wrapped we'll remove any transfer encoding at this point.
- */
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- IOUtils.copy(in, out);
- in.close();
- in = null; // we want all of our memory back, and close might not release
-
- /*
- * We've got a text part, so let's see if it needs to be processed further.
- */
- String charset = getHeaderParameter(part.getContentType(), "charset");
- if (charset != null) {
- /*
- * See if there is conversion from the MIME charset to the Java one.
- */
- charset = CharsetUtil.toJavaCharset(charset);
- }
- /*
- * No encoding, so use us-ascii, which is the standard.
- */
- if (charset == null) {
- charset = "ASCII";
- }
- /*
- * Convert and return as new String
- */
- String result = out.toString(charset);
- out.close();
- return result;
- }
- }
-
- }
- catch (OutOfMemoryError oom) {
- /*
- * If we are not able to process the body there's nothing we can do about it. Return
- * null and let the upper layers handle the missing content.
- */
- Log.e(Logging.LOG_TAG, "Unable to getTextFromPart " + oom.toString());
- }
- catch (Exception e) {
- /*
- * If we are not able to process the body there's nothing we can do about it. Return
- * null and let the upper layers handle the missing content.
- */
- Log.e(Logging.LOG_TAG, "Unable to getTextFromPart " + e.toString());
- }
- return null;
- }
-
- /**
- * Returns true if the given mimeType matches the matchAgainst specification. The comparison
- * ignores case and the matchAgainst string may include "*" for a wildcard (e.g. "image/*").
- *
- * @param mimeType A MIME type to check.
- * @param matchAgainst A MIME type to check against. May include wildcards.
- * @return true if the mimeType matches
- */
- public static boolean mimeTypeMatches(String mimeType, String matchAgainst) {
- Pattern p = Pattern.compile(matchAgainst.replaceAll("\\*", "\\.\\*"),
- Pattern.CASE_INSENSITIVE);
- return p.matcher(mimeType).matches();
- }
-
- /**
- * Returns true if the given mimeType matches any of the matchAgainst specifications. The
- * comparison ignores case and the matchAgainst strings may include "*" for a wildcard
- * (e.g. "image/*").
- *
- * @param mimeType A MIME type to check.
- * @param matchAgainst An array of MIME types to check against. May include wildcards.
- * @return true if the mimeType matches any of the matchAgainst strings
- */
- public static boolean mimeTypeMatches(String mimeType, String[] matchAgainst) {
- for (String matchType : matchAgainst) {
- if (mimeTypeMatches(mimeType, matchType)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Given an input stream and a transfer encoding, return a wrapped input stream for that
- * encoding (or the original if none is required)
- * @param in the input stream
- * @param contentTransferEncoding the content transfer encoding
- * @return a properly wrapped stream
- */
- public static InputStream getInputStreamForContentTransferEncoding(InputStream in,
- String contentTransferEncoding) {
- if (contentTransferEncoding != null) {
- contentTransferEncoding =
- MimeUtility.getHeaderParameter(contentTransferEncoding, null);
- if ("quoted-printable".equalsIgnoreCase(contentTransferEncoding)) {
- in = new QuotedPrintableInputStream(in);
- }
- else if ("base64".equalsIgnoreCase(contentTransferEncoding)) {
- in = new Base64InputStream(in, Base64.DEFAULT);
- }
- }
- return in;
- }
-
- /**
- * Removes any content transfer encoding from the stream and returns a Body.
- */
- public static Body decodeBody(InputStream in, String contentTransferEncoding)
- throws IOException {
- /*
- * We'll remove any transfer encoding by wrapping the stream.
- */
- in = getInputStreamForContentTransferEncoding(in, contentTransferEncoding);
- BinaryTempFileBody tempBody = new BinaryTempFileBody();
- OutputStream out = tempBody.getOutputStream();
- try {
- IOUtils.copy(in, out);
- } catch (Base64DataException bde) {
- // TODO Need to fix this somehow
- //String warning = "\n\n" + Email.getMessageDecodeErrorString();
- //out.write(warning.getBytes());
- } finally {
- out.close();
- }
- return tempBody;
- }
-
- /**
- * Recursively scan a Part (usually a Message) and sort out which of its children will be
- * "viewable" and which will be attachments.
- *
- * @param part The part to be broken down
- * @param viewables This arraylist will be populated with all parts that appear to be
- * the "message" (e.g. text/plain & text/html)
- * @param attachments This arraylist will be populated with all parts that appear to be
- * attachments (including inlines)
- * @throws MessagingException
- */
- public static void collectParts(Part part, ArrayList<Part> viewables,
- ArrayList<Part> attachments) throws MessagingException {
- String disposition = part.getDisposition();
- String dispositionType = MimeUtility.getHeaderParameter(disposition, null);
- // If a disposition is not specified, default to "inline"
- boolean inline =
- TextUtils.isEmpty(dispositionType) || "inline".equalsIgnoreCase(dispositionType);
- // The lower-case mime type
- String mimeType = part.getMimeType().toLowerCase();
-
- if (part.getBody() instanceof Multipart) {
- // If the part is Multipart but not alternative it's either mixed or
- // something we don't know about, which means we treat it as mixed
- // per the spec. We just process its pieces recursively.
- MimeMultipart mp = (MimeMultipart)part.getBody();
- boolean foundHtml = false;
- if (mp.getSubTypeForTest().equals("alternative")) {
- for (int i = 0; i < mp.getCount(); i++) {
- if (mp.getBodyPart(i).isMimeType("text/html")) {
- foundHtml = true;
- break;
- }
- }
- }
- for (int i = 0; i < mp.getCount(); i++) {
- // See if we have text and html
- BodyPart bp = mp.getBodyPart(i);
- // If there's html, don't bother loading text
- if (foundHtml && bp.isMimeType("text/plain")) {
- continue;
- }
- collectParts(bp, viewables, attachments);
- }
- } else if (part.getBody() instanceof Message) {
- // If the part is an embedded message we just continue to process
- // it, pulling any viewables or attachments into the running list.
- Message message = (Message)part.getBody();
- collectParts(message, viewables, attachments);
- } else if (inline && (mimeType.startsWith("text") || (mimeType.startsWith("image")))) {
- // We'll treat text and images as viewables
- viewables.add(part);
- } else {
- // Everything else is an attachment.
- attachments.add(part);
- }
- }
-}
diff --git a/emailcommon/src/com/android/emailcommon/internet/TextBody.java b/emailcommon/src/com/android/emailcommon/internet/TextBody.java
deleted file mode 100644
index 09c265c8e..000000000
--- a/emailcommon/src/com/android/emailcommon/internet/TextBody.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed 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 com.android.emailcommon.internet;
-
-import com.android.emailcommon.mail.Body;
-import com.android.emailcommon.mail.MessagingException;
-
-import android.util.Base64;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-
-public class TextBody implements Body {
- String mBody;
-
- public TextBody(String body) {
- this.mBody = body;
- }
-
- public void writeTo(OutputStream out) throws IOException, MessagingException {
- byte[] bytes = mBody.getBytes("UTF-8");
- out.write(Base64.encode(bytes, Base64.CRLF));
- }
-
- /**
- * Get the text of the body in it's unencoded format.
- * @return
- */
- public String getText() {
- return mBody;
- }
-
- /**
- * Returns an InputStream that reads this body's text in UTF-8 format.
- */
- public InputStream getInputStream() throws MessagingException {
- try {
- byte[] b = mBody.getBytes("UTF-8");
- return new ByteArrayInputStream(b);
- }
- catch (UnsupportedEncodingException usee) {
- return null;
- }
- }
-}