diff --git a/emailcommon/Android.mk b/emailcommon/Android.mk index 55f9525ca..e731d0a1c 100644 --- a/emailcommon/Android.mk +++ b/emailcommon/Android.mk @@ -25,9 +25,6 @@ unified_email_src_dir := ../../UnifiedEmail/src apache_src_dir := ../../UnifiedEmail/src/org imported_unified_email_files := \ - $(unified_email_unified_src_dir)/com/android/mail/utils/LogTag.java \ - $(unified_email_src_dir)/com/android/mail/preferences/BasePreferenceMigrator.java \ - $(unified_email_unified_src_dir)/com/android/mail/preferences/PreferenceMigrator.java \ $(unified_email_src_dir)/com/android/mail/utils/LogUtils.java \ $(unified_email_src_dir)/com/android/mail/providers/UIProvider.java @@ -41,6 +38,7 @@ LOCAL_SRC_FILES += \ src/com/android/emailcommon/service/IAccountService.aidl LOCAL_SRC_FILES += $(call all-java-files-under, $(apache_src_dir)) LOCAL_SRC_FILES += $(imported_unified_email_files) +LOCAL_SRC_FILES += $(call all-java-files-under, $(unified_email_src_dir)/com/android/emailcommon) LOCAL_SDK_VERSION := 14 diff --git a/emailcommon/src/com/android/emailcommon/TempDirectory.java b/emailcommon/src/com/android/emailcommon/TempDirectory.java deleted file mode 100644 index 252488c9f..000000000 --- a/emailcommon/src/com/android/emailcommon/TempDirectory.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2011 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; - -import android.content.Context; - -import java.io.File; - -/** - * TempDirectory caches the directory used for caching file. It is set up during application - * initialization. - */ -public class TempDirectory { - private static File sTempDirectory = null; - - public static void setTempDirectory(Context context) { - sTempDirectory = context.getCacheDir(); - } - - public static File getTempDirectory() { - if (sTempDirectory == null) { - throw new RuntimeException( - "TempDirectory not set. " + - "If in a unit test, call Email.setTempDirectory(context) in setUp()."); - } - return sTempDirectory; - } -} 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 mFields = new ArrayList(); - - 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 values = new ArrayList(); - 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 removeFields = new ArrayList(); - 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 stack = new Stack(); - - 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 RFC - * 2047 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 viewables, - ArrayList 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; - } - } -} diff --git a/emailcommon/src/com/android/emailcommon/mail/Address.java b/emailcommon/src/com/android/emailcommon/mail/Address.java deleted file mode 100644 index 5245c5691..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/Address.java +++ /dev/null @@ -1,428 +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.mail; - -import android.text.TextUtils; -import android.text.util.Rfc822Token; -import android.text.util.Rfc822Tokenizer; - -import com.android.emailcommon.utility.Utility; -import com.google.common.annotations.VisibleForTesting; - -import org.apache.james.mime4j.codec.EncoderUtil; -import org.apache.james.mime4j.decoder.DecoderUtil; - -import java.util.ArrayList; -import java.util.regex.Pattern; - -/** - * This class represent email address. - * - * RFC822 email address may have following format. - * "name"
(comment) - * "name"
- * name
- * address - * Name and comment part should be MIME/base64 encoded in header if necessary. - * - */ -public class Address { - /** - * Address part, in the form local_part@domain_part. No surrounding angle brackets. - */ - private String mAddress; - - /** - * Name part. No surrounding double quote, and no MIME/base64 encoding. - * This must be null if Address has no name part. - */ - private String mPersonal; - - // Regex that matches address surrounded by '<>' optionally. '^]+)>?$' - private static final Pattern REMOVE_OPTIONAL_BRACKET = Pattern.compile("^]+)>?$"); - // Regex that matches personal name surrounded by '""' optionally. '^"?([^"]+)"?$' - private static final Pattern REMOVE_OPTIONAL_DQUOTE = Pattern.compile("^\"?([^\"]*)\"?$"); - // Regex that matches escaped character '\\([\\"])' - private static final Pattern UNQUOTE = Pattern.compile("\\\\([\\\\\"])"); - - private static final Address[] EMPTY_ADDRESS_ARRAY = new Address[0]; - - // delimiters are chars that do not appear in an email address, used by pack/unpack - private static final char LIST_DELIMITER_EMAIL = '\1'; - private static final char LIST_DELIMITER_PERSONAL = '\2'; - - public Address(String address, String personal) { - setAddress(address); - setPersonal(personal); - } - - public Address(String address) { - setAddress(address); - } - - public String getAddress() { - return mAddress; - } - - public void setAddress(String address) { - mAddress = REMOVE_OPTIONAL_BRACKET.matcher(address).replaceAll("$1"); - } - - /** - * Get name part as UTF-16 string. No surrounding double quote, and no MIME/base64 encoding. - * - * @return Name part of email address. Returns null if it is omitted. - */ - public String getPersonal() { - return mPersonal; - } - - /** - * Set name part from UTF-16 string. Optional surrounding double quote will be removed. - * It will be also unquoted and MIME/base64 decoded. - * - * @param personal name part of email address as UTF-16 string. Null is acceptable. - */ - public void setPersonal(String personal) { - if (personal != null) { - personal = REMOVE_OPTIONAL_DQUOTE.matcher(personal).replaceAll("$1"); - personal = UNQUOTE.matcher(personal).replaceAll("$1"); - personal = DecoderUtil.decodeEncodedWords(personal); - if (personal.length() == 0) { - personal = null; - } - } - mPersonal = personal; - } - - /** - * This method is used to check that all the addresses that the user - * entered in a list (e.g. To:) are valid, so that none is dropped. - */ - public static boolean isAllValid(String addressList) { - // This code mimics the parse() method below. - // I don't know how to better avoid the code-duplication. - if (addressList != null && addressList.length() > 0) { - Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(addressList); - for (int i = 0, length = tokens.length; i < length; ++i) { - Rfc822Token token = tokens[i]; - String address = token.getAddress(); - if (!TextUtils.isEmpty(address) && !isValidAddress(address)) { - return false; - } - } - } - return true; - } - - /** - * Parse a comma-delimited list of addresses in RFC822 format and return an - * array of Address objects. - * - * @param addressList Address list in comma-delimited string. - * @return An array of 0 or more Addresses. - */ - public static Address[] parse(String addressList) { - if (addressList == null || addressList.length() == 0) { - return EMPTY_ADDRESS_ARRAY; - } - Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(addressList); - ArrayList
addresses = new ArrayList
(); - for (int i = 0, length = tokens.length; i < length; ++i) { - Rfc822Token token = tokens[i]; - String address = token.getAddress(); - if (!TextUtils.isEmpty(address)) { - if (isValidAddress(address)) { - String name = token.getName(); - if (TextUtils.isEmpty(name)) { - name = null; - } - addresses.add(new Address(address, name)); - } - } - } - return addresses.toArray(new Address[] {}); - } - - /** - * Checks whether a string email address is valid. - * E.g. name@domain.com is valid. - */ - @VisibleForTesting - static boolean isValidAddress(String address) { - // Note: Some email provider may violate the standard, so here we only check that - // address consists of two part that are separated by '@', and domain part contains - // at least one '.'. - int len = address.length(); - int firstAt = address.indexOf('@'); - int lastAt = address.lastIndexOf('@'); - int firstDot = address.indexOf('.', lastAt + 1); - int lastDot = address.lastIndexOf('.'); - return firstAt > 0 && firstAt == lastAt && lastAt + 1 < firstDot - && firstDot <= lastDot && lastDot < len - 1; - } - - @Override - public boolean equals(Object o) { - if (o instanceof Address) { - // It seems that the spec says that the "user" part is case-sensitive, - // while the domain part in case-insesitive. - // So foo@yahoo.com and Foo@yahoo.com are different. - // This may seem non-intuitive from the user POV, so we - // may re-consider it if it creates UI trouble. - // A problem case is "replyAll" sending to both - // a@b.c and to A@b.c, which turn out to be the same on the server. - // Leave unchanged for now (i.e. case-sensitive). - return getAddress().equals(((Address) o).getAddress()); - } - return super.equals(o); - } - - public int hashCode() { - return getAddress().hashCode(); - } - - /** - * Get human readable address string. - * Do not use this for email header. - * - * @return Human readable address string. Not quoted and not encoded. - */ - @Override - public String toString() { - if (mPersonal != null && !mPersonal.equals(mAddress)) { - if (mPersonal.matches(".*[\\(\\)<>@,;:\\\\\".\\[\\]].*")) { - return Utility.quoteString(mPersonal) + " <" + mAddress + ">"; - } else { - return mPersonal + " <" + mAddress + ">"; - } - } else { - return mAddress; - } - } - - /** - * Get human readable comma-delimited address string. - * - * @param addresses Address array - * @return Human readable comma-delimited address string. - */ - public static String toString(Address[] addresses) { - return toString(addresses, ","); - } - - /** - * Get human readable address strings joined with the specified separator. - * - * @param addresses Address array - * @param separator Separator - * @return Human readable comma-delimited address string. - */ - public static String toString(Address[] addresses, String separator) { - if (addresses == null || addresses.length == 0) { - return null; - } - if (addresses.length == 1) { - return addresses[0].toString(); - } - StringBuffer sb = new StringBuffer(addresses[0].toString()); - for (int i = 1; i < addresses.length; i++) { - sb.append(separator); - // TODO: investigate why this .trim() is needed. - sb.append(addresses[i].toString().trim()); - } - return sb.toString(); - } - - /** - * Get RFC822/MIME compatible address string. - * - * @return RFC822/MIME compatible address string. - * It may be surrounded by double quote or quoted and MIME/base64 encoded if necessary. - */ - public String toHeader() { - if (mPersonal != null) { - return EncoderUtil.encodeAddressDisplayName(mPersonal) + " <" + mAddress + ">"; - } else { - return mAddress; - } - } - - /** - * Get RFC822/MIME compatible comma-delimited address string. - * - * @param addresses Address array - * @return RFC822/MIME compatible comma-delimited address string. - * it may be surrounded by double quoted or quoted and MIME/base64 encoded if necessary. - */ - public static String toHeader(Address[] addresses) { - if (addresses == null || addresses.length == 0) { - return null; - } - if (addresses.length == 1) { - return addresses[0].toHeader(); - } - StringBuffer sb = new StringBuffer(addresses[0].toHeader()); - for (int i = 1; i < addresses.length; i++) { - // We need space character to be able to fold line. - sb.append(", "); - sb.append(addresses[i].toHeader()); - } - return sb.toString(); - } - - /** - * Get Human friendly address string. - * - * @return the personal part of this Address, or the address part if the - * personal part is not available - */ - public String toFriendly() { - if (mPersonal != null && mPersonal.length() > 0) { - return mPersonal; - } else { - return mAddress; - } - } - - /** - * Creates a comma-delimited list of addresses in the "friendly" format (see toFriendly() for - * details on the per-address conversion). - * - * @param addresses Array of Address[] values - * @return A comma-delimited string listing all of the addresses supplied. Null if source - * was null or empty. - */ - public static String toFriendly(Address[] addresses) { - if (addresses == null || addresses.length == 0) { - return null; - } - if (addresses.length == 1) { - return addresses[0].toFriendly(); - } - StringBuffer sb = new StringBuffer(addresses[0].toFriendly()); - for (int i = 1; i < addresses.length; i++) { - sb.append(", "); - sb.append(addresses[i].toFriendly()); - } - return sb.toString(); - } - - /** - * Returns exactly the same result as Address.toString(Address.unpack(packedList)). - */ - public static String unpackToString(String packedList) { - return toString(unpack(packedList)); - } - - /** - * Returns exactly the same result as Address.pack(Address.parse(textList)). - */ - public static String parseAndPack(String textList) { - return Address.pack(Address.parse(textList)); - } - - /** - * Returns null if the packedList has 0 addresses, otherwise returns the first address. - * The same as Address.unpack(packedList)[0] for non-empty list. - * This is an utility method that offers some performance optimization opportunities. - */ - public static Address unpackFirst(String packedList) { - Address[] array = unpack(packedList); - return array.length > 0 ? array[0] : null; - } - - /** - * Convert a packed list of addresses to a form suitable for use in an RFC822 header. - * This implementation is brute-force, and could be replaced with a more efficient version - * if desired. - */ - public static String packedToHeader(String packedList) { - return toHeader(unpack(packedList)); - } - - /** - * Unpacks an address list that is either CSV of RFC822 addresses OR (for backward - * compatibility) previously packed with pack() - * @param addressList string packed with pack() or CSV of RFC822 addresses - * @return array of addresses resulting from unpack - */ - public static Address[] unpack(String addressList) { - if (addressList == null || addressList.length() == 0) { - return EMPTY_ADDRESS_ARRAY; - } - // IF we're CSV, just parse - if ((addressList.indexOf(LIST_DELIMITER_PERSONAL) == -1) && - (addressList.indexOf(LIST_DELIMITER_EMAIL) == -1)) { - return Address.parse(addressList); - } - // Otherwise, do backward-compatibile unpack - ArrayList
addresses = new ArrayList
(); - int length = addressList.length(); - int pairStartIndex = 0; - int pairEndIndex = 0; - - /* addressEndIndex is only re-scanned (indexOf()) when a LIST_DELIMITER_PERSONAL - is used, not for every email address; i.e. not for every iteration of the while(). - This reduces the theoretical complexity from quadratic to linear, - and provides some speed-up in practice by removing redundant scans of the string. - */ - int addressEndIndex = addressList.indexOf(LIST_DELIMITER_PERSONAL); - - while (pairStartIndex < length) { - pairEndIndex = addressList.indexOf(LIST_DELIMITER_EMAIL, pairStartIndex); - if (pairEndIndex == -1) { - pairEndIndex = length; - } - Address address; - if (addressEndIndex == -1 || pairEndIndex <= addressEndIndex) { - // in this case the DELIMITER_PERSONAL is in a future pair, - // so don't use personal, and don't update addressEndIndex - address = new Address(addressList.substring(pairStartIndex, pairEndIndex), null); - } else { - address = new Address(addressList.substring(pairStartIndex, addressEndIndex), - addressList.substring(addressEndIndex + 1, pairEndIndex)); - // only update addressEndIndex when we use the LIST_DELIMITER_PERSONAL - addressEndIndex = addressList.indexOf(LIST_DELIMITER_PERSONAL, pairEndIndex + 1); - } - addresses.add(address); - pairStartIndex = pairEndIndex + 1; - } - return addresses.toArray(EMPTY_ADDRESS_ARRAY); - } - - /** - * Generate a String containing RFC822 addresses separated by commas - * NOTE: We used to "pack" these addresses in an app-specific format, but no longer do so - */ - public static String pack(Address[] addresses) { - return Address.toHeader(addresses); - } - - /** - * Produces the same result as pack(array), but only packs one (this) address. - */ - public String pack() { - final String address = getAddress(); - final String personal = getPersonal(); - if (personal == null) { - return address; - } else { - return address + LIST_DELIMITER_PERSONAL + personal; - } - } -} diff --git a/emailcommon/src/com/android/emailcommon/mail/AuthenticationFailedException.java b/emailcommon/src/com/android/emailcommon/mail/AuthenticationFailedException.java deleted file mode 100644 index af8d96c09..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/AuthenticationFailedException.java +++ /dev/null @@ -1,34 +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.mail; - - -public class AuthenticationFailedException extends MessagingException { - public static final long serialVersionUID = -1; - - public AuthenticationFailedException(String message) { - super(MessagingException.AUTHENTICATION_FAILED, message); - } - - public AuthenticationFailedException(int exceptionType, String message) { - super(exceptionType, message); - } - - public AuthenticationFailedException(String message, Throwable throwable) { - super(MessagingException.AUTHENTICATION_FAILED, message, throwable); - } -} diff --git a/emailcommon/src/com/android/emailcommon/mail/Body.java b/emailcommon/src/com/android/emailcommon/mail/Body.java deleted file mode 100644 index 841ab42a7..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/Body.java +++ /dev/null @@ -1,26 +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.mail; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public interface Body { - public InputStream getInputStream() throws MessagingException; - public void writeTo(OutputStream out) throws IOException, MessagingException; -} diff --git a/emailcommon/src/com/android/emailcommon/mail/BodyPart.java b/emailcommon/src/com/android/emailcommon/mail/BodyPart.java deleted file mode 100644 index f698a139d..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/BodyPart.java +++ /dev/null @@ -1,25 +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.mail; - -public abstract class BodyPart implements Part { - protected Multipart mParent; - - public Multipart getParent() { - return mParent; - } -} diff --git a/emailcommon/src/com/android/emailcommon/mail/CertificateValidationException.java b/emailcommon/src/com/android/emailcommon/mail/CertificateValidationException.java deleted file mode 100644 index 83c6224df..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/CertificateValidationException.java +++ /dev/null @@ -1,30 +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.mail; - - -public class CertificateValidationException extends MessagingException { - public static final long serialVersionUID = -1; - - public CertificateValidationException(String message) { - super(MessagingException.CERTIFICATE_VALIDATION_ERROR, message); - } - - public CertificateValidationException(String message, Throwable throwable) { - super(MessagingException.CERTIFICATE_VALIDATION_ERROR, message, throwable); - } -} \ No newline at end of file diff --git a/emailcommon/src/com/android/emailcommon/mail/FetchProfile.java b/emailcommon/src/com/android/emailcommon/mail/FetchProfile.java deleted file mode 100644 index bfa48d30f..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/FetchProfile.java +++ /dev/null @@ -1,85 +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.mail; - -import java.util.ArrayList; - -/** - *
- * A FetchProfile is a list of items that should be downloaded in bulk for a set of messages.
- * FetchProfile can contain the following objects:
- *      FetchProfile.Item:      Described below.
- *      Message:                Indicates that the body of the entire message should be fetched.
- *                              Synonymous with FetchProfile.Item.BODY.
- *      Part:                   Indicates that the given Part should be fetched. The provider
- *                              is expected have previously created the given BodyPart and stored
- *                              any information it needs to download the content.
- * 
- */ -public class FetchProfile extends ArrayList { - /** - * Default items available for pre-fetching. It should be expected that any - * item fetched by using these items could potentially include all of the - * previous items. - */ - public enum Item implements Fetchable { - /** - * Download the flags of the message. - */ - FLAGS, - - /** - * Download the envelope of the message. This should include at minimum - * the size and the following headers: date, subject, from, content-type, to, cc - */ - ENVELOPE, - - /** - * Download the structure of the message. This maps directly to IMAP's BODYSTRUCTURE - * and may map to other providers. - * The provider should, if possible, fill in a properly formatted MIME structure in - * the message without actually downloading any message data. If the provider is not - * capable of this operation it should specifically set the body of the message to null - * so that upper levels can detect that a full body download is needed. - */ - STRUCTURE, - - /** - * A sane portion of the entire message, cut off at a provider determined limit. - * This should generaly be around 50kB. - */ - BODY_SANE, - - /** - * The entire message. - */ - BODY, - } - - /** - * @return the first {@link Part} in this collection, or null if it doesn't contain - * {@link Part}. - */ - public Part getFirstPart() { - for (Fetchable o : this) { - if (o instanceof Part) { - return (Part) o; - } - } - return null; - } -} diff --git a/emailcommon/src/com/android/emailcommon/mail/Fetchable.java b/emailcommon/src/com/android/emailcommon/mail/Fetchable.java deleted file mode 100644 index 4314f93f5..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/Fetchable.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2010 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.mail; - -/** - * Interface for classes that can be added to {@link FetchProfile}. - * i.e. {@link Part} and its subclasses, and {@link FetchProfile.Item}. - */ -public interface Fetchable { -} diff --git a/emailcommon/src/com/android/emailcommon/mail/Flag.java b/emailcommon/src/com/android/emailcommon/mail/Flag.java deleted file mode 100644 index bcdcb8b7e..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/Flag.java +++ /dev/null @@ -1,79 +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.mail; - -/** - * Flags that can be applied to Messages. - */ -public enum Flag { - - // If adding new flags: ALL FLAGS MUST BE UPPER CASE. - - DELETED, - SEEN, - ANSWERED, - FLAGGED, - DRAFT, - RECENT, - - /* - * The following flags are for internal library use only. - * TODO Eventually we should creates a Flags class that extends ArrayList that allows - * these flags and Strings to represent user defined flags. At that point the below - * flags should become user defined flags. - */ - /** - * Delete and remove from the LocalStore immediately. - */ - X_DESTROYED, - - /** - * Sending of an unsent message failed. It will be retried. Used to show status. - */ - X_SEND_FAILED, - - /** - * Sending of an unsent message is in progress. - */ - X_SEND_IN_PROGRESS, - - /** - * Indicates that a message is fully downloaded from the server and can be viewed normally. - * This does not include attachments, which are never downloaded fully. - */ - X_DOWNLOADED_FULL, - - /** - * Indicates that a message is partially downloaded from the server and can be viewed but - * more content is available on the server. - * This does not include attachments, which are never downloaded fully. - */ - X_DOWNLOADED_PARTIAL, - - /** - * General purpose flag that can be used by any remote store. The flag will be - * saved and restored by the LocalStore. - */ - X_STORE_1, - - /** - * General purpose flag that can be used by any remote store. The flag will be - * saved and restored by the LocalStore. - */ - X_STORE_2, - -} diff --git a/emailcommon/src/com/android/emailcommon/mail/Folder.java b/emailcommon/src/com/android/emailcommon/mail/Folder.java deleted file mode 100644 index c58988d96..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/Folder.java +++ /dev/null @@ -1,209 +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.mail; - -import com.android.emailcommon.service.SearchParams; -import com.google.common.annotations.VisibleForTesting; - - -public abstract class Folder { - public enum OpenMode { - READ_WRITE, READ_ONLY, - } - - public enum FolderType { - HOLDS_FOLDERS, HOLDS_MESSAGES, - } - - /** - * Identifiers of "special" folders. - */ - public enum FolderRole { - INBOX, // NOTE: The folder's name must be INBOX - TRASH, - SENT, - DRAFTS, - - OUTBOX, // Local folders only - not used in remote Stores - OTHER, // this folder has no specific role - UNKNOWN // the role of this folder is unknown - } - - /** - * Callback for each message retrieval. - * - * Not all {@link Folder} implementations may invoke it. - */ - public interface MessageRetrievalListener { - public void messageRetrieved(Message message); - public void loadAttachmentProgress(int progress); - } - - /** - * Forces an open of the MailProvider. If the provider is already open this - * function returns without doing anything. - * - * @param mode READ_ONLY or READ_WRITE - * @param callbacks Pointer to callbacks class. This may be used by the folder between this - * time and when close() is called. This is only used for remote stores - should be null - * for LocalStore.LocalFolder. - */ - public abstract void open(OpenMode mode) - throws MessagingException; - - /** - * Forces a close of the MailProvider. Any further access will attempt to - * reopen the MailProvider. - * - * @param expunge If true all deleted messages will be expunged. - */ - public abstract void close(boolean expunge) throws MessagingException; - - /** - * @return True if further commands are not expected to have to open the - * connection. - */ - @VisibleForTesting - public abstract boolean isOpen(); - - /** - * Returns the mode the folder was opened with. This may be different than the mode the open - * was requested with. - */ - public abstract OpenMode getMode() throws MessagingException; - - /** - * Reports if the Store is able to create folders of the given type. - * Does not actually attempt to create a folder. - * @param type - * @return true if can create, false if cannot create - */ - public abstract boolean canCreate(FolderType type); - - /** - * Attempt to create the given folder remotely using the given type. - * @return true if created, false if cannot create (e.g. server side) - */ - public abstract boolean create(FolderType type) throws MessagingException; - - public abstract boolean exists() throws MessagingException; - - /** - * Returns the number of messages in the selected folder. - */ - public abstract int getMessageCount() throws MessagingException; - - public abstract int getUnreadMessageCount() throws MessagingException; - - public abstract Message getMessage(String uid) throws MessagingException; - - /** - * Fetches the given list of messages. The specified listener is notified as - * each fetch completes. Messages are downloaded as (as) lightweight (as - * possible) objects to be filled in with later requests. In most cases this - * means that only the UID is downloaded. - */ - public abstract Message[] getMessages(int start, int end, MessageRetrievalListener listener) - throws MessagingException; - - public abstract Message[] getMessages(SearchParams params,MessageRetrievalListener listener) - throws MessagingException; - - public abstract Message[] getMessages(String[] uids, MessageRetrievalListener listener) - throws MessagingException; - - /** - * Return a set of messages based on the state of the flags. - * Note: Not typically implemented in remote stores, so not abstract. - * - * @param setFlags The flags that should be set for a message to be selected (can be null) - * @param clearFlags The flags that should be clear for a message to be selected (can be null) - * @param listener - * @return A list of messages matching the desired flag states. - * @throws MessagingException - */ - public Message[] getMessages(Flag[] setFlags, Flag[] clearFlags, - MessageRetrievalListener listener) throws MessagingException { - throw new MessagingException("Not implemented"); - } - - public abstract void appendMessages(Message[] messages) throws MessagingException; - - /** - * Copies the given messages to the destination folder. - */ - public abstract void copyMessages(Message[] msgs, Folder folder, - MessageUpdateCallbacks callbacks) throws MessagingException; - - public abstract void setFlags(Message[] messages, Flag[] flags, boolean value) - throws MessagingException; - - public abstract Message[] expunge() throws MessagingException; - - public abstract void fetch(Message[] messages, FetchProfile fp, - MessageRetrievalListener listener) throws MessagingException; - - public abstract void delete(boolean recurse) throws MessagingException; - - public abstract String getName(); - - public abstract Flag[] getPermanentFlags() throws MessagingException; - - /** - * This method returns a string identifying the name of a "role" folder - * (such as inbox, draft, sent, or trash). Stores that do not implement this - * feature can be used - the account UI will provide default strings. To - * let the server identify specific folder roles, simply override this method. - * - * @return The server- or protocol- specific role for this folder. If some roles are known - * but this is not one of them, return FolderRole.OTHER. If roles are unsupported here, - * return FolderRole.UNKNOWN. - */ - public FolderRole getRole() { - return FolderRole.UNKNOWN; - } - - /** - * Create an empty message of the appropriate type for the Folder. - */ - public abstract Message createMessage(String uid) throws MessagingException; - - /** - * Callback interface by which a folder can report UID changes caused by certain operations. - */ - public interface MessageUpdateCallbacks { - /** - * The operation caused the message's UID to change - * @param message The message for which the UID changed - * @param newUid The new UID for the message - */ - public void onMessageUidChange(Message message, String newUid) throws MessagingException; - - /** - * The operation could not be completed because the message doesn't exist - * (for example, it was already deleted from the server side.) - * @param message The message that does not exist - * @throws MessagingException - */ - public void onMessageNotFound(Message message) throws MessagingException; - } - - @Override - public String toString() { - return getName(); - } -} diff --git a/emailcommon/src/com/android/emailcommon/mail/MeetingInfo.java b/emailcommon/src/com/android/emailcommon/mail/MeetingInfo.java deleted file mode 100644 index 87637f7a1..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/MeetingInfo.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2010 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.mail; - -public class MeetingInfo { - // Predefined tags; others can be added - public static final String MEETING_DTSTAMP = "DTSTAMP"; - public static final String MEETING_UID = "UID"; - public static final String MEETING_ORGANIZER_EMAIL = "ORGMAIL"; - public static final String MEETING_DTSTART = "DTSTART"; - public static final String MEETING_DTEND = "DTEND"; - public static final String MEETING_TITLE = "TITLE"; - public static final String MEETING_LOCATION = "LOC"; - public static final String MEETING_RESPONSE_REQUESTED = "RESPONSE"; - public static final String MEETING_ALL_DAY = "ALLDAY"; -} diff --git a/emailcommon/src/com/android/emailcommon/mail/Message.java b/emailcommon/src/com/android/emailcommon/mail/Message.java deleted file mode 100644 index 09aef87d1..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/Message.java +++ /dev/null @@ -1,159 +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.mail; - -import java.util.Date; -import java.util.HashSet; - -public abstract class Message implements Part, Body { - public static final Message[] EMPTY_ARRAY = new Message[0]; - - public enum RecipientType { - TO, CC, BCC, - } - - protected String mUid; - - private HashSet mFlags = null; - - protected Date mInternalDate; - - protected Folder mFolder; - - public String getUid() { - return mUid; - } - - public void setUid(String uid) { - this.mUid = uid; - } - - public Folder getFolder() { - return mFolder; - } - - public abstract String getSubject() throws MessagingException; - - public abstract void setSubject(String subject) throws MessagingException; - - public Date getInternalDate() { - return mInternalDate; - } - - public void setInternalDate(Date internalDate) { - this.mInternalDate = internalDate; - } - - public abstract Date getReceivedDate() throws MessagingException; - - public abstract Date getSentDate() throws MessagingException; - - public abstract void setSentDate(Date sentDate) throws MessagingException; - - public abstract Address[] getRecipients(RecipientType type) throws MessagingException; - - public abstract void setRecipients(RecipientType type, Address[] addresses) - throws MessagingException; - - public void setRecipient(RecipientType type, Address address) throws MessagingException { - setRecipients(type, new Address[] { - address - }); - } - - public abstract Address[] getFrom() throws MessagingException; - - public abstract void setFrom(Address from) throws MessagingException; - - public abstract Address[] getReplyTo() throws MessagingException; - - public abstract void setReplyTo(Address[] from) throws MessagingException; - - public abstract Body getBody() throws MessagingException; - - public abstract String getContentType() throws MessagingException; - - public abstract void addHeader(String name, String value) throws MessagingException; - - public abstract void setHeader(String name, String value) throws MessagingException; - - public abstract String[] getHeader(String name) throws MessagingException; - - public abstract void removeHeader(String name) throws MessagingException; - - // Always use these instead of getHeader("Message-ID") or setHeader("Message-ID"); - public abstract void setMessageId(String messageId) throws MessagingException; - public abstract String getMessageId() throws MessagingException; - - public abstract void setBody(Body body) throws MessagingException; - - public boolean isMimeType(String mimeType) throws MessagingException { - return getContentType().startsWith(mimeType); - } - - private HashSet getFlagSet() { - if (mFlags == null) { - mFlags = new HashSet(); - } - return mFlags; - } - - /* - * TODO Refactor Flags at some point to be able to store user defined flags. - */ - public Flag[] getFlags() { - return getFlagSet().toArray(new Flag[] {}); - } - - /** - * Set/clear a flag directly, without involving overrides of {@link #setFlag} in subclasses. - * Only used for testing. - */ - public final void setFlagDirectlyForTest(Flag flag, boolean set) throws MessagingException { - if (set) { - getFlagSet().add(flag); - } else { - getFlagSet().remove(flag); - } - } - - public void setFlag(Flag flag, boolean set) throws MessagingException { - setFlagDirectlyForTest(flag, set); - } - - /** - * This method calls setFlag(Flag, boolean) - * @param flags - * @param set - */ - public void setFlags(Flag[] flags, boolean set) throws MessagingException { - for (Flag flag : flags) { - setFlag(flag, set); - } - } - - public boolean isSet(Flag flag) { - return getFlagSet().contains(flag); - } - - public abstract void saveChanges() throws MessagingException; - - @Override - public String toString() { - return getClass().getSimpleName() + ':' + mUid; - } -} diff --git a/emailcommon/src/com/android/emailcommon/mail/MessageDateComparator.java b/emailcommon/src/com/android/emailcommon/mail/MessageDateComparator.java deleted file mode 100644 index 0b1a55115..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/MessageDateComparator.java +++ /dev/null @@ -1,34 +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.mail; - -import java.util.Comparator; - -public class MessageDateComparator implements Comparator { - public int compare(Message o1, Message o2) { - try { - if (o1.getSentDate() == null) { - return 1; - } else if (o2.getSentDate() == null) { - return -1; - } else - return o2.getSentDate().compareTo(o1.getSentDate()); - } catch (Exception e) { - return 0; - } - } -} diff --git a/emailcommon/src/com/android/emailcommon/mail/MessagingException.java b/emailcommon/src/com/android/emailcommon/mail/MessagingException.java deleted file mode 100644 index 4a8cebade..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/MessagingException.java +++ /dev/null @@ -1,136 +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.mail; - - -/** - * This exception is used for most types of failures that occur during server interactions. - * - * Data passed through this exception should be considered non-localized. Any strings should - * either be internal-only (for debugging) or server-generated. - * - * TO DO: Does it make sense to further collapse AuthenticationFailedException and - * CertificateValidationException and any others into this? - */ -public class MessagingException extends Exception { - public static final long serialVersionUID = -1; - - public static final int NO_ERROR = -1; - /** Any exception that does not specify a specific issue */ - public static final int UNSPECIFIED_EXCEPTION = 0; - /** Connection or IO errors */ - public static final int IOERROR = 1; - /** The configuration requested TLS but the server did not support it. */ - public static final int TLS_REQUIRED = 2; - /** Authentication is required but the server did not support it. */ - public static final int AUTH_REQUIRED = 3; - /** General security failures */ - public static final int GENERAL_SECURITY = 4; - /** Authentication failed */ - public static final int AUTHENTICATION_FAILED = 5; - /** Attempt to create duplicate account */ - public static final int DUPLICATE_ACCOUNT = 6; - /** Required security policies reported - advisory only */ - public static final int SECURITY_POLICIES_REQUIRED = 7; - /** Required security policies not supported */ - public static final int SECURITY_POLICIES_UNSUPPORTED = 8; - /** The protocol (or protocol version) isn't supported */ - public static final int PROTOCOL_VERSION_UNSUPPORTED = 9; - /** The server's SSL certificate couldn't be validated */ - public static final int CERTIFICATE_VALIDATION_ERROR = 10; - /** Authentication failed during autodiscover */ - public static final int AUTODISCOVER_AUTHENTICATION_FAILED = 11; - /** Autodiscover completed with a result (non-error) */ - public static final int AUTODISCOVER_AUTHENTICATION_RESULT = 12; - /** Ambiguous failure; server error or bad credentials */ - public static final int AUTHENTICATION_FAILED_OR_SERVER_ERROR = 13; - /** The server refused access */ - public static final int ACCESS_DENIED = 14; - /** The server refused access */ - public static final int ATTACHMENT_NOT_FOUND = 15; - /** A client SSL certificate is required for connections to the server */ - public static final int CLIENT_CERTIFICATE_REQUIRED = 16; - /** The client SSL certificate specified is invalid */ - public static final int CLIENT_CERTIFICATE_ERROR = 17; - - protected int mExceptionType; - // Exception type-specific data - protected Object mExceptionData; - - public MessagingException(String message, Throwable throwable) { - this(UNSPECIFIED_EXCEPTION, message, throwable); - } - - public MessagingException(int exceptionType, String message, Throwable throwable) { - super(message, throwable); - mExceptionType = exceptionType; - mExceptionData = null; - } - - /** - * Constructs a MessagingException with an exceptionType and a null message. - * @param exceptionType The exception type to set for this exception. - */ - public MessagingException(int exceptionType) { - this(exceptionType, null, null); - } - - /** - * Constructs a MessagingException with a message. - * @param message the message for this exception - */ - public MessagingException(String message) { - this(UNSPECIFIED_EXCEPTION, message, null); - } - - /** - * Constructs a MessagingException with an exceptionType and a message. - * @param exceptionType The exception type to set for this exception. - */ - public MessagingException(int exceptionType, String message) { - this(exceptionType, message, null); - } - - /** - * Constructs a MessagingException with an exceptionType, a message, and data - * @param exceptionType The exception type to set for this exception. - * @param message the message for the exception (or null) - * @param data exception-type specific data for the exception (or null) - */ - public MessagingException(int exceptionType, String message, Object data) { - super(message); - mExceptionType = exceptionType; - mExceptionData = data; - } - - /** - * Return the exception type. Will be OTHER_EXCEPTION if not explicitly set. - * - * @return Returns the exception type. - */ - public int getExceptionType() { - return mExceptionType; - } - /** - * Return the exception data. Will be null if not explicitly set. - * - * @return Returns the exception data. - */ - public Object getExceptionData() { - return mExceptionData; - } -} \ No newline at end of file diff --git a/emailcommon/src/com/android/emailcommon/mail/Multipart.java b/emailcommon/src/com/android/emailcommon/mail/Multipart.java deleted file mode 100644 index 4a1a06714..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/Multipart.java +++ /dev/null @@ -1,63 +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.mail; - -import java.util.ArrayList; - -public abstract class Multipart implements Body { - protected Part mParent; - - protected ArrayList mParts = new ArrayList(); - - protected String mContentType; - - public void addBodyPart(BodyPart part) throws MessagingException { - mParts.add(part); - } - - public void addBodyPart(BodyPart part, int index) throws MessagingException { - mParts.add(index, part); - } - - public BodyPart getBodyPart(int index) throws MessagingException { - return mParts.get(index); - } - - public String getContentType() throws MessagingException { - return mContentType; - } - - public int getCount() throws MessagingException { - return mParts.size(); - } - - public boolean removeBodyPart(BodyPart part) throws MessagingException { - return mParts.remove(part); - } - - public void removeBodyPart(int index) throws MessagingException { - mParts.remove(index); - } - - public Part getParent() throws MessagingException { - return mParent; - } - - public void setParent(Part parent) throws MessagingException { - this.mParent = parent; - } -} diff --git a/emailcommon/src/com/android/emailcommon/mail/PackedString.java b/emailcommon/src/com/android/emailcommon/mail/PackedString.java deleted file mode 100644 index de5fe4692..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/PackedString.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2010 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.mail; - -import java.util.HashMap; -import java.util.Map; - -/** - * A utility class for creating and modifying Strings that are tagged and packed together. - * - * Uses non-printable (control chars) for internal delimiters; Intended for regular displayable - * strings only, so please use base64 or other encoding if you need to hide any binary data here. - * - * Binary compatible with Address.pack() format, which should migrate to use this code. - */ -public class PackedString { - - /** - * Packing format is: - * element : [ value ] or [ value TAG-DELIMITER tag ] - * packed-string : [ element ] [ ELEMENT-DELIMITER [ element ] ]* - */ - private static final char DELIMITER_ELEMENT = '\1'; - private static final char DELIMITER_TAG = '\2'; - - private String mString; - private HashMap mExploded; - private static final HashMap EMPTY_MAP = new HashMap(); - - /** - * Create a packed string using an already-packed string (e.g. from database) - * @param string packed string - */ - public PackedString(String string) { - mString = string; - mExploded = null; - } - - /** - * Get the value referred to by a given tag. If the tag does not exist, return null. - * @param tag identifier of string of interest - * @return returns value, or null if no string is found - */ - public String get(String tag) { - if (mExploded == null) { - mExploded = explode(mString); - } - return mExploded.get(tag); - } - - /** - * Return a map of all of the values referred to by a given tag. This is a shallow - * copy, don't edit the values. - * @return a map of the values in the packed string - */ - public Map unpack() { - if (mExploded == null) { - mExploded = explode(mString); - } - return new HashMap(mExploded); - } - - /** - * Read out all values into a map. - */ - private static HashMap explode(String packed) { - if (packed == null || packed.length() == 0) { - return EMPTY_MAP; - } - HashMap map = new HashMap(); - - int length = packed.length(); - int elementStartIndex = 0; - int elementEndIndex = 0; - int tagEndIndex = packed.indexOf(DELIMITER_TAG); - - while (elementStartIndex < length) { - elementEndIndex = packed.indexOf(DELIMITER_ELEMENT, elementStartIndex); - if (elementEndIndex == -1) { - elementEndIndex = length; - } - String tag; - String value; - if (tagEndIndex == -1 || elementEndIndex <= tagEndIndex) { - // in this case the DELIMITER_PERSONAL is in a future pair (or not found) - // so synthesize a positional tag for the value, and don't update tagEndIndex - value = packed.substring(elementStartIndex, elementEndIndex); - tag = Integer.toString(map.size()); - } else { - value = packed.substring(elementStartIndex, tagEndIndex); - tag = packed.substring(tagEndIndex + 1, elementEndIndex); - // scan forward for next tag, if any - tagEndIndex = packed.indexOf(DELIMITER_TAG, elementEndIndex + 1); - } - map.put(tag, value); - elementStartIndex = elementEndIndex + 1; - } - - return map; - } - - /** - * Builder class for creating PackedString values. Can also be used for editing existing - * PackedString representations. - */ - static public class Builder { - HashMap mMap; - - /** - * Create a builder that's empty (for filling) - */ - public Builder() { - mMap = new HashMap(); - } - - /** - * Create a builder using the values of an existing PackedString (for editing). - */ - public Builder(String packed) { - mMap = explode(packed); - } - - /** - * Add a tagged value - * @param tag identifier of string of interest - * @param value the value to record in this position. null to delete entry. - */ - public void put(String tag, String value) { - if (value == null) { - mMap.remove(tag); - } else { - mMap.put(tag, value); - } - } - - /** - * Get the value referred to by a given tag. If the tag does not exist, return null. - * @param tag identifier of string of interest - * @return returns value, or null if no string is found - */ - public String get(String tag) { - return mMap.get(tag); - } - - /** - * Pack the values and return a single, encoded string - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - for (Map.Entry entry : mMap.entrySet()) { - if (sb.length() > 0) { - sb.append(DELIMITER_ELEMENT); - } - sb.append(entry.getValue()); - sb.append(DELIMITER_TAG); - sb.append(entry.getKey()); - } - return sb.toString(); - } - } -} diff --git a/emailcommon/src/com/android/emailcommon/mail/Part.java b/emailcommon/src/com/android/emailcommon/mail/Part.java deleted file mode 100644 index eeb233ca9..000000000 --- a/emailcommon/src/com/android/emailcommon/mail/Part.java +++ /dev/null @@ -1,52 +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.mail; - -import java.io.IOException; -import java.io.OutputStream; - -public interface Part extends Fetchable { - public void addHeader(String name, String value) throws MessagingException; - - public void removeHeader(String name) throws MessagingException; - - public void setHeader(String name, String value) throws MessagingException; - - public Body getBody() throws MessagingException; - - public String getContentType() throws MessagingException; - - public String getDisposition() throws MessagingException; - - public String getContentId() throws MessagingException; - - public String[] getHeader(String name) throws MessagingException; - - public void setExtendedHeader(String name, String value) throws MessagingException; - - public String getExtendedHeader(String name) throws MessagingException; - - public int getSize() throws MessagingException; - - public boolean isMimeType(String mimeType) throws MessagingException; - - public String getMimeType() throws MessagingException; - - public void setBody(Body body) throws MessagingException; - - public void writeTo(OutputStream out) throws IOException, MessagingException; -} diff --git a/emailcommon/src/com/android/emailcommon/service/SearchParams.java b/emailcommon/src/com/android/emailcommon/service/SearchParams.java deleted file mode 100644 index eacf01df9..000000000 --- a/emailcommon/src/com/android/emailcommon/service/SearchParams.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2011 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.service; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.android.emailcommon.provider.Mailbox; -import com.google.common.base.Objects; - -public class SearchParams implements Parcelable { - public static final long ALL_MAILBOXES = Mailbox.NO_MAILBOX; - - private static final int DEFAULT_LIMIT = 10; // Need input on what this number should be - private static final int DEFAULT_OFFSET = 0; - - // The id of the mailbox to be searched; if -1, all mailboxes MUST be searched - public final long mMailboxId; - // If true, all subfolders of the specified mailbox MUST be searched - public boolean mIncludeChildren = true; - // The search terms (the search MUST only select messages whose contents include all of the - // search terms in the query) - public final String mFilter; - // The maximum number of results to be created by this search - public int mLimit = DEFAULT_LIMIT; - // If zero, specifies a "new" search; otherwise, asks for a continuation of the previous - // query(ies) starting with the mOffset'th match (0 based) - public int mOffset = DEFAULT_OFFSET; - // The total number of results for this search - public int mTotalCount = 0; - // The id of the "search" mailbox being used - public long mSearchMailboxId; - - /** - * Error codes returned by the searchMessages API - */ - public static class SearchParamsError { - public static final int CANT_SEARCH_ALL_MAILBOXES = -1; - public static final int CANT_SEARCH_CHILDREN = -2; - } - - public SearchParams(long mailboxId, String filter) { - mMailboxId = mailboxId; - mFilter = filter; - } - - public SearchParams(long mailboxId, String filter, long searchMailboxId) { - mMailboxId = mailboxId; - mFilter = filter; - mSearchMailboxId = searchMailboxId; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if ((o == null) || !(o instanceof SearchParams)) { - return false; - } - - SearchParams os = (SearchParams) o; - return mMailboxId == os.mMailboxId - && mIncludeChildren == os.mIncludeChildren - && mFilter.equals(os.mFilter) - && mLimit == os.mLimit - && mOffset == os.mOffset; - } - - @Override - public int hashCode() { - return Objects.hashCode(mMailboxId, mFilter, mOffset); - } - - @Override - public String toString() { - return "[SearchParams " + mMailboxId + ":" + mFilter + " (" + mOffset + ", " + mLimit + "]"; - } - - @Override - public int describeContents() { - return 0; - } - - /** - * Supports Parcelable - */ - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - @Override - public SearchParams createFromParcel(Parcel in) { - return new SearchParams(in); - } - - @Override - public SearchParams[] newArray(int size) { - return new SearchParams[size]; - } - }; - - /** - * Supports Parcelable - */ - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(mMailboxId); - dest.writeInt(mIncludeChildren ? 1 : 0); - dest.writeString(mFilter); - dest.writeInt(mLimit); - dest.writeInt(mOffset); - } - - /** - * Supports Parcelable - */ - public SearchParams(Parcel in) { - mMailboxId = in.readLong(); - mIncludeChildren = in.readInt() == 1; - mFilter = in.readString(); - mLimit = in.readInt(); - mOffset = in.readInt(); - } -} diff --git a/emailcommon/src/com/android/emailcommon/utility/Utility.java b/emailcommon/src/com/android/emailcommon/utility/Utility.java index b17fa9a98..b0f019ccf 100644 --- a/emailcommon/src/com/android/emailcommon/utility/Utility.java +++ b/emailcommon/src/com/android/emailcommon/utility/Utility.java @@ -211,34 +211,6 @@ public class Utility { } } - /** - * Ensures that the given string starts and ends with the double quote character. The string is - * not modified in any way except to add the double quote character to start and end if it's not - * already there. - * - * TODO: Rename this, because "quoteString()" can mean so many different things. - * - * sample -> "sample" - * "sample" -> "sample" - * ""sample"" -> "sample" - * "sample"" -> "sample" - * sa"mp"le -> "sa"mp"le" - * "sa"mp"le" -> "sa"mp"le" - * (empty string) -> "" - * " -> "" - */ - public static String quoteString(String s) { - if (s == null) { - return null; - } - if (!s.matches("^\".*\"$")) { - return "\"" + s + "\""; - } - else { - return s; - } - } - /** * A fast version of URLDecoder.decode() that works only with UTF-8 and does only two * allocations. This version is around 3x as fast as the standard one and I'm using it