13ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira/**
23ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira * Copyright (c) 2012, Google Inc.
33ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira *
43ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License");
53ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira * you may not use this file except in compliance with the License.
63ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira * You may obtain a copy of the License at
73ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira *
83ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira *     http://www.apache.org/licenses/LICENSE-2.0
93ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira *
103ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira * Unless required by applicable law or agreed to in writing, software
113ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS,
123ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira * See the License for the specific language governing permissions and
143ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira * limitations under the License.
153ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira */
163ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
173ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereirapackage com.android.mail.providers;
183ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
193233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huangimport android.content.AsyncQueryHandler;
203233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huangimport android.content.ContentValues;
217434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport android.content.Context;
223ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereiraimport android.database.Cursor;
23cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereiraimport android.net.Uri;
243ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereiraimport android.os.Parcel;
253ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereiraimport android.os.Parcelable;
26e623a0f6e3caa9cafec913cf826e946628833517Andy Huangimport android.provider.BaseColumns;
27014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huangimport android.text.Html;
288d6e803bf63d5dad5cb0187c82171e42147e8a44Yu Ping Huimport android.text.SpannableString;
29cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereiraimport android.text.TextUtils;
308d6e803bf63d5dad5cb0187c82171e42147e8a44Yu Ping Huimport android.text.util.Linkify;
315ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindypimport android.text.util.Rfc822Token;
325ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindypimport android.text.util.Rfc822Tokenizer;
333ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
34934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieuximport com.android.emailcommon.internet.MimeHeader;
358812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.emailcommon.internet.MimeMessage;
368812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.emailcommon.internet.MimeUtility;
37934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieuximport com.android.emailcommon.mail.Address;
388812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.emailcommon.mail.MessagingException;
398812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.emailcommon.mail.Part;
408812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport com.android.emailcommon.utility.ConversionUtilities;
4126846d859a4714ff90ea02dba251a54cac1f1e9fMarc Blankimport com.android.mail.providers.UIProvider.MessageColumns;
42606dbd7a44b8445e872c25c0fe080e3e12a47adfAndrew Sappersteinimport com.android.mail.ui.HtmlMessage;
4327a36a6bbeebb6cfd53ad2766463d71ab4b26ce0James Lemieuximport com.android.mail.utils.HtmlSanitizer;
4426846d859a4714ff90ea02dba251a54cac1f1e9fMarc Blankimport com.android.mail.utils.Utils;
452bae2f5ef13424f8d932f5e45a2e276b531ecfe6Martin Hibdonimport com.google.common.annotations.VisibleForTesting;
46cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huangimport com.google.common.base.Objects;
477434e800d4313a227120ca36bd95683752a7879fAndrew Sappersteinimport com.google.common.collect.Lists;
4826846d859a4714ff90ea02dba251a54cac1f1e9fMarc Blank
498812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sappersteinimport java.util.ArrayList;
509ab47b16e0189d219c16e2eddfbd66c741c01229Andy Huangimport java.util.Collections;
5120dbbd66471f23520fbddf63c5af6a517839f5e8Andrew Sappersteinimport java.util.Date;
525a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huangimport java.util.List;
5341dca185f7683b36bdafd9520c0648c897a95834Paul Westbrookimport java.util.regex.Pattern;
545a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
553ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
56606dbd7a44b8445e872c25c0fe080e3e12a47adfAndrew Sappersteinpublic class Message implements Parcelable, HtmlMessage {
57e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
5841dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook     * Regex pattern used to look for any inline images in message bodies, including Gmail-hosted
5941dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook     * relative-URL images, Gmail emoticons, and any external inline images (although we usually
6041dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook     * count on the server to detect external images).
6141dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook     */
6241dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook    private static Pattern INLINE_IMAGE_PATTERN = Pattern.compile("<img\\s+[^>]*src=",
6341dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook            Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
6441dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook
65934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux    // regex that matches content id surrounded by "<>" optionally.
66934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux    private static final Pattern REMOVE_OPTIONAL_BRACKETS = Pattern.compile("^<?([^>]+)>?$");
67934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux
6841dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook    /**
69e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see BaseColumns#_ID
70e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
713ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public long id;
72e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
73e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#SERVER_ID
74e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
75d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang    public String serverId;
76e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
77e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#URI
78e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
79cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira    public Uri uri;
80e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
81e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#CONVERSATION_ID
82e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
83daa06aba887e8e3748453f45ae52c1e571fe9f2eAndy Huang    public Uri conversationUri;
84e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
85e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#SUBJECT
86e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
873ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public String subject;
88e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
89e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#SNIPPET
90e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
913ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public String snippet;
92e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
93e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#FROM
94e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
958960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    private String mFrom;
96e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
97e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#TO
98e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
998960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    private String mTo;
100e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
101e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#CC
102e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1038960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    private String mCc;
104e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
105e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#BCC
106e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1078960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    private String mBcc;
108e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
109e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#REPLY_TO
110e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1118960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    private String mReplyTo;
112e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
113e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#DATE_RECEIVED_MS
114e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1153ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public long dateReceivedMs;
116e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
117e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#BODY_HTML
118e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1193ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public String bodyHtml;
120e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
121e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#BODY_TEXT
122e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1233ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public String bodyText;
124e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
125e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#EMBEDS_EXTERNAL_RESOURCES
126e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1273ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public boolean embedsExternalResources;
128e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
129e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#REF_MESSAGE_ID
130e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
131a990a715012379451344246c5156d29938f12886Alice Yang    public Uri refMessageUri;
132e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
133e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#DRAFT_TYPE
134e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1353ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public int draftType;
136e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
137e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#APPEND_REF_MESSAGE_CONTENT
138e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1393ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public boolean appendRefMessageContent;
140e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
141e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#HAS_ATTACHMENTS
142e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1433ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public boolean hasAttachments;
144e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
145e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#ATTACHMENT_LIST_URI
146e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
147cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira    public Uri attachmentListUri;
148e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
149934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux     * @see UIProvider.MessageColumns#ATTACHMENT_BY_CID_URI
150934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux     */
151934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux    public Uri attachmentByCidUri;
152934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux    /**
153e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#MESSAGE_FLAGS
154e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1553ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public long messageFlags;
156e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
157e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#ALWAYS_SHOW_IMAGES
158e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
159104f729c284f9b7b31a251350252f8ae31d09f86Paul Westbrook    public boolean alwaysShowImages;
160e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
161e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#READ
162e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
163d8e249ee7abb0e1ad24e17e4e299736d4a150936Andy Huang    public boolean read;
164e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
165d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy     * @see UIProvider.MessageColumns#SEEN
166d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy     */
167d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy    public boolean seen;
168d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy    /**
169e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#STARRED
170e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
171d8e249ee7abb0e1ad24e17e4e299736d4a150936Andy Huang    public boolean starred;
172e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
173e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#QUOTE_START_POS
174e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1754dbbf9f91da20d89b13d412038c0b19b91983f8cMindy Pereira    public int quotedTextOffset;
176e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
177e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#ATTACHMENTS
1786766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang     *<p>
1796766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang     * N.B. this value is NOT immutable and may change during conversation view render.
180e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1815a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    public String attachmentsJson;
182e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
183e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#MESSAGE_ACCOUNT_URI
184e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
18562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira    public Uri accountUri;
186e623a0f6e3caa9cafec913cf826e946628833517Andy Huang    /**
187e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     * @see UIProvider.MessageColumns#EVENT_INTENT_URI
188e623a0f6e3caa9cafec913cf826e946628833517Andy Huang     */
1893842af9e8ba90ebf5b75dc5018bbfdfb2e044f99Marc Blank    public Uri eventIntentUri;
190d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein    /**
191d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein     * @see UIProvider.MessageColumns#SPAM_WARNING_STRING
192d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein     */
1933b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein    public String spamWarningString;
194d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein    /**
195d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein     * @see UIProvider.MessageColumns#SPAM_WARNING_LEVEL
196d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein     */
1973b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein    public int spamWarningLevel;
198d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein    /**
199d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein     * @see UIProvider.MessageColumns#SPAM_WARNING_LINK_TYPE
200d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein     */
2013b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein    public int spamLinkType;
202d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein    /**
203d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein     * @see UIProvider.MessageColumns#VIA_DOMAIN
204d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein     */
205d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein    public String viaDomain;
20647aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang    /**
2076a2df258316b267151296556dbbdba20200ecb1fJin Cao     * @see UIProvider.MessageColumns#SENDING_STATE
20847aa9c991b33c722a6ba1946fc02e0aba17bc1c9Andy Huang     */
2096a2df258316b267151296556dbbdba20200ecb1fJin Cao    public int sendingState;
2105a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
211f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein    /**
212f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein     * @see UIProvider.MessageColumns#CLIPPED
213f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein     */
214f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein    public boolean clipped;
21520c2082e85e87dc9c70b3d74e20ed31d3eff7364Andrew Sapperstein    /**
21620c2082e85e87dc9c70b3d74e20ed31d3eff7364Andrew Sapperstein     * @see UIProvider.MessageColumns#PERMALINK
21720c2082e85e87dc9c70b3d74e20ed31d3eff7364Andrew Sapperstein     */
21820c2082e85e87dc9c70b3d74e20ed31d3eff7364Andrew Sapperstein    public String permalink;
219f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein
220d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein    private transient String[] mFromAddresses = null;
2215a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    private transient String[] mToAddresses = null;
2225a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    private transient String[] mCcAddresses = null;
2235a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    private transient String[] mBccAddresses = null;
2245a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    private transient String[] mReplyToAddresses = null;
2253ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
2265a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    private transient List<Attachment> mAttachments = null;
227845f87e34179bcbb2862c09572576ab775be472dmindyp
2283ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    @Override
2293ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public int describeContents() {
2303ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        return 0;
2313ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    }
2323ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
2333ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    @Override
2343233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang    public boolean equals(Object o) {
235cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang        return this == o || (o != null && o instanceof Message
236cd5c5eeae167885ffa2959c200233fea2f39c5f7Andy Huang                && Objects.equal(uri, ((Message) o).uri));
2373233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang    }
2383233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang
2393233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang    @Override
2403233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang    public int hashCode() {
2413233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang        return uri == null ? 0 : uri.hashCode();
2423233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang    }
2433233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang
2442ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao    /**
2452ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao     * Helper equality function to check if the two Message objects are equal in terms of
2462ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao     * the fields that the user can input from ComposeActivity. This is primarily used to
2472ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao     * ensure draft preview/composition are synced.
2482ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao     * @param o the Message being compared to
2492ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao     * @return True if they are equal in fields, false otherwise
2502ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao     */
2512ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao    public boolean isEqual(Message o) {
2522ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao        return TextUtils.equals(this.getFrom(), o.getFrom()) &&
2536a2df258316b267151296556dbbdba20200ecb1fJin Cao                this.sendingState == o.sendingState &&
2542ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao                TextUtils.equals(this.getTo(), o.getTo()) &&
2552ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao                TextUtils.equals(this.getCc(), o.getCc()) &&
2562ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao                TextUtils.equals(this.getBcc(), o.getBcc()) &&
2572ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao                TextUtils.equals(this.subject, o.subject) &&
2582ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao                TextUtils.equals(this.bodyHtml, o.bodyHtml) &&
2592ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao                TextUtils.equals(this.bodyText, o.bodyText) &&
26023caa3ec923cd3bdbe1dcf0af454e1047cfbb26dJin Cao                Objects.equal(this.attachmentListUri, o.attachmentListUri) &&
26123caa3ec923cd3bdbe1dcf0af454e1047cfbb26dJin Cao                Objects.equal(getAttachments(), o.getAttachments());
2622ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao    }
2632ef5f08719a9981d73f7954ce82a78ea6842f187Jin Cao
2643233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang    @Override
2653ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public void writeToParcel(Parcel dest, int flags) {
2663ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dest.writeLong(id);
267d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang        dest.writeString(serverId);
268cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        dest.writeParcelable(uri, 0);
269daa06aba887e8e3748453f45ae52c1e571fe9f2eAndy Huang        dest.writeParcelable(conversationUri, 0);
2703ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dest.writeString(subject);
2713ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dest.writeString(snippet);
2728960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        dest.writeString(mFrom);
2738960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        dest.writeString(mTo);
2748960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        dest.writeString(mCc);
2758960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        dest.writeString(mBcc);
2768960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        dest.writeString(mReplyTo);
2773ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dest.writeLong(dateReceivedMs);
2783ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dest.writeString(bodyHtml);
2793ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dest.writeString(bodyText);
2803ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dest.writeInt(embedsExternalResources ? 1 : 0);
281a990a715012379451344246c5156d29938f12886Alice Yang        dest.writeParcelable(refMessageUri, 0);
2823ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dest.writeInt(draftType);
2833ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dest.writeInt(appendRefMessageContent ? 1 : 0);
2843ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dest.writeInt(hasAttachments ? 1 : 0);
285cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        dest.writeParcelable(attachmentListUri, 0);
2863ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dest.writeLong(messageFlags);
287104f729c284f9b7b31a251350252f8ae31d09f86Paul Westbrook        dest.writeInt(alwaysShowImages ? 1 : 0);
2884dbbf9f91da20d89b13d412038c0b19b91983f8cMindy Pereira        dest.writeInt(quotedTextOffset);
2892421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira        dest.writeString(attachmentsJson);
29062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        dest.writeParcelable(accountUri, 0);
2913842af9e8ba90ebf5b75dc5018bbfdfb2e044f99Marc Blank        dest.writeParcelable(eventIntentUri, 0);
2923b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein        dest.writeString(spamWarningString);
2933b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein        dest.writeInt(spamWarningLevel);
2943b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein        dest.writeInt(spamLinkType);
295d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein        dest.writeString(viaDomain);
2966a2df258316b267151296556dbbdba20200ecb1fJin Cao        dest.writeInt(sendingState);
297f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein        dest.writeInt(clipped ? 1 : 0);
29820c2082e85e87dc9c70b3d74e20ed31d3eff7364Andrew Sapperstein        dest.writeString(permalink);
2993ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    }
3003ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
3013ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    private Message(Parcel in) {
3023ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        id = in.readLong();
303d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang        serverId = in.readString();
304cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        uri = in.readParcelable(null);
305daa06aba887e8e3748453f45ae52c1e571fe9f2eAndy Huang        conversationUri = in.readParcelable(null);
3063ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        subject = in.readString();
3073ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        snippet = in.readString();
3088960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mFrom = in.readString();
3098960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mTo = in.readString();
3108960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mCc = in.readString();
3118960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mBcc = in.readString();
3128960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mReplyTo = in.readString();
3133ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        dateReceivedMs = in.readLong();
3143ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        bodyHtml = in.readString();
3153ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        bodyText = in.readString();
3163ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        embedsExternalResources = in.readInt() != 0;
317a990a715012379451344246c5156d29938f12886Alice Yang        refMessageUri = in.readParcelable(null);
3183ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        draftType = in.readInt();
3193ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        appendRefMessageContent = in.readInt() != 0;
3203ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        hasAttachments = in.readInt() != 0;
321cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira        attachmentListUri = in.readParcelable(null);
3223ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        messageFlags = in.readLong();
323104f729c284f9b7b31a251350252f8ae31d09f86Paul Westbrook        alwaysShowImages = in.readInt() != 0;
3244dbbf9f91da20d89b13d412038c0b19b91983f8cMindy Pereira        quotedTextOffset = in.readInt();
3252421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira        attachmentsJson = in.readString();
32662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira        accountUri = in.readParcelable(null);
3273842af9e8ba90ebf5b75dc5018bbfdfb2e044f99Marc Blank        eventIntentUri = in.readParcelable(null);
3283b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein        spamWarningString = in.readString();
3293b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein        spamWarningLevel = in.readInt();
3303b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein        spamLinkType = in.readInt();
331d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein        viaDomain = in.readString();
3326a2df258316b267151296556dbbdba20200ecb1fJin Cao        sendingState = in.readInt();
333f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein        clipped = in.readInt() != 0;
33420c2082e85e87dc9c70b3d74e20ed31d3eff7364Andrew Sapperstein        permalink = in.readString();
335104f729c284f9b7b31a251350252f8ae31d09f86Paul Westbrook    }
336104f729c284f9b7b31a251350252f8ae31d09f86Paul Westbrook
337104f729c284f9b7b31a251350252f8ae31d09f86Paul Westbrook    public Message() {
338104f729c284f9b7b31a251350252f8ae31d09f86Paul Westbrook
3393ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    }
3403ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
3413ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    @Override
3423ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public String toString() {
3433ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        return "[message id=" + id + "]";
3443ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    }
3453ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
3463ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    public static final Creator<Message> CREATOR = new Creator<Message>() {
3473ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
3483ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        @Override
3493ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        public Message createFromParcel(Parcel source) {
3503ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            return new Message(source);
3513ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        }
3523ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
3533ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        @Override
3543ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        public Message[] newArray(int size) {
3553ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            return new Message[size];
3563ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        }
3573ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
3583ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    };
3593ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira
360a831b2f1ba6d3c18d5e54563df8bae1f589c4257Mindy Pereira    public Message(Cursor cursor) {
3613ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        if (cursor != null) {
3623ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            id = cursor.getLong(UIProvider.MESSAGE_ID_COLUMN);
363d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang            serverId = cursor.getString(UIProvider.MESSAGE_SERVER_ID_COLUMN);
364daa06aba887e8e3748453f45ae52c1e571fe9f2eAndy Huang            final String messageUriStr = cursor.getString(UIProvider.MESSAGE_URI_COLUMN);
365daa06aba887e8e3748453f45ae52c1e571fe9f2eAndy Huang            uri = !TextUtils.isEmpty(messageUriStr) ? Uri.parse(messageUriStr) : null;
366daa06aba887e8e3748453f45ae52c1e571fe9f2eAndy Huang            final String convUriStr = cursor.getString(UIProvider.MESSAGE_CONVERSATION_URI_COLUMN);
367daa06aba887e8e3748453f45ae52c1e571fe9f2eAndy Huang            conversationUri = !TextUtils.isEmpty(convUriStr) ? Uri.parse(convUriStr) : null;
3683ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            subject = cursor.getString(UIProvider.MESSAGE_SUBJECT_COLUMN);
3693ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            snippet = cursor.getString(UIProvider.MESSAGE_SNIPPET_COLUMN);
3708960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy            mFrom = cursor.getString(UIProvider.MESSAGE_FROM_COLUMN);
3718960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy            mTo = cursor.getString(UIProvider.MESSAGE_TO_COLUMN);
3728960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy            mCc = cursor.getString(UIProvider.MESSAGE_CC_COLUMN);
3738960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy            mBcc = cursor.getString(UIProvider.MESSAGE_BCC_COLUMN);
3748960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy            mReplyTo = cursor.getString(UIProvider.MESSAGE_REPLY_TO_COLUMN);
3753ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            dateReceivedMs = cursor.getLong(UIProvider.MESSAGE_DATE_RECEIVED_MS_COLUMN);
3763ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            bodyHtml = cursor.getString(UIProvider.MESSAGE_BODY_HTML_COLUMN);
3773ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            bodyText = cursor.getString(UIProvider.MESSAGE_BODY_TEXT_COLUMN);
3783ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            embedsExternalResources = cursor
3793ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira                    .getInt(UIProvider.MESSAGE_EMBEDS_EXTERNAL_RESOURCES_COLUMN) != 0;
380a990a715012379451344246c5156d29938f12886Alice Yang            final String refMessageUriStr =
381a990a715012379451344246c5156d29938f12886Alice Yang                    cursor.getString(UIProvider.MESSAGE_REF_MESSAGE_URI_COLUMN);
382a990a715012379451344246c5156d29938f12886Alice Yang            refMessageUri = !TextUtils.isEmpty(refMessageUriStr) ?
383a990a715012379451344246c5156d29938f12886Alice Yang                    Uri.parse(refMessageUriStr) : null;
3843ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            draftType = cursor.getInt(UIProvider.MESSAGE_DRAFT_TYPE_COLUMN);
3853ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            appendRefMessageContent = cursor
3863ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira                    .getInt(UIProvider.MESSAGE_APPEND_REF_MESSAGE_CONTENT_COLUMN) != 0;
3873ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            hasAttachments = cursor.getInt(UIProvider.MESSAGE_HAS_ATTACHMENTS_COLUMN) != 0;
3887bb27253d9eb377d13da55b67b0babd047eca367Mindy Pereira            final String attachmentsUri = cursor
3897bb27253d9eb377d13da55b67b0babd047eca367Mindy Pereira                    .getString(UIProvider.MESSAGE_ATTACHMENT_LIST_URI_COLUMN);
3907bb27253d9eb377d13da55b67b0babd047eca367Mindy Pereira            attachmentListUri = hasAttachments && !TextUtils.isEmpty(attachmentsUri) ? Uri
3917bb27253d9eb377d13da55b67b0babd047eca367Mindy Pereira                    .parse(attachmentsUri) : null;
392934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            final String attachmentsByCidUri = cursor
393934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux                    .getString(UIProvider.MESSAGE_ATTACHMENT_BY_CID_URI_COLUMN);
394934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            attachmentByCidUri = hasAttachments && !TextUtils.isEmpty(attachmentsByCidUri) ?
395934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux                    Uri.parse(attachmentsByCidUri) : null;
3963ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira            messageFlags = cursor.getLong(UIProvider.MESSAGE_FLAGS_COLUMN);
397d8e249ee7abb0e1ad24e17e4e299736d4a150936Andy Huang            alwaysShowImages = cursor.getInt(UIProvider.MESSAGE_ALWAYS_SHOW_IMAGES_COLUMN) != 0;
398d8e249ee7abb0e1ad24e17e4e299736d4a150936Andy Huang            read = cursor.getInt(UIProvider.MESSAGE_READ_COLUMN) != 0;
399d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy            seen = cursor.getInt(UIProvider.MESSAGE_SEEN_COLUMN) != 0;
400d8e249ee7abb0e1ad24e17e4e299736d4a150936Andy Huang            starred = cursor.getInt(UIProvider.MESSAGE_STARRED_COLUMN) != 0;
4014dbbf9f91da20d89b13d412038c0b19b91983f8cMindy Pereira            quotedTextOffset = cursor.getInt(UIProvider.QUOTED_TEXT_OFFSET_COLUMN);
4025a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang            attachmentsJson = cursor.getString(UIProvider.MESSAGE_ATTACHMENTS_COLUMN);
40362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            String accountUriString = cursor.getString(UIProvider.MESSAGE_ACCOUNT_URI_COLUMN);
40462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira            accountUri = !TextUtils.isEmpty(accountUriString) ? Uri.parse(accountUriString) : null;
4053842af9e8ba90ebf5b75dc5018bbfdfb2e044f99Marc Blank            eventIntentUri =
4063842af9e8ba90ebf5b75dc5018bbfdfb2e044f99Marc Blank                    Utils.getValidUri(cursor.getString(UIProvider.MESSAGE_EVENT_INTENT_COLUMN));
4073b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein            spamWarningString =
4083b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein                    cursor.getString(UIProvider.MESSAGE_SPAM_WARNING_STRING_ID_COLUMN);
4093b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein            spamWarningLevel = cursor.getInt(UIProvider.MESSAGE_SPAM_WARNING_LEVEL_COLUMN);
4103b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein            spamLinkType = cursor.getInt(UIProvider.MESSAGE_SPAM_WARNING_LINK_TYPE_COLUMN);
411d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein            viaDomain = cursor.getString(UIProvider.MESSAGE_VIA_DOMAIN_COLUMN);
4126a2df258316b267151296556dbbdba20200ecb1fJin Cao            sendingState = cursor.getInt(UIProvider.MESSAGE_SENDING_STATE_COLUMN);
413f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein            clipped = cursor.getInt(UIProvider.MESSAGE_CLIPPED_COLUMN) != 0;
41420c2082e85e87dc9c70b3d74e20ed31d3eff7364Andrew Sapperstein            permalink = cursor.getString(UIProvider.MESSAGE_PERMALINK_COLUMN);
4153ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira        }
4163ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira    }
4170a22047bb6c54d8f1ce980762f75908e35b08c3dAndy Huang
41827a36a6bbeebb6cfd53ad2766463d71ab4b26ce0James Lemieux    /**
41927a36a6bbeebb6cfd53ad2766463d71ab4b26ce0James Lemieux     * This constructor exists solely to generate Message objects from .eml attachments.
42027a36a6bbeebb6cfd53ad2766463d71ab4b26ce0James Lemieux     */
4217434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein    public Message(Context context, MimeMessage mimeMessage, Uri emlFileUri)
4227434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein            throws MessagingException {
4238812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        // Set message header values.
4244d3e937bb3ca208c320e8a124c6f26079c4090d0James Lemieux        setFrom(Address.toHeader(mimeMessage.getFrom()));
4254d3e937bb3ca208c320e8a124c6f26079c4090d0James Lemieux        setTo(Address.toHeader(mimeMessage.getRecipients(
4268812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein                com.android.emailcommon.mail.Message.RecipientType.TO)));
4274d3e937bb3ca208c320e8a124c6f26079c4090d0James Lemieux        setCc(Address.toHeader(mimeMessage.getRecipients(
4288812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein                com.android.emailcommon.mail.Message.RecipientType.CC)));
4294d3e937bb3ca208c320e8a124c6f26079c4090d0James Lemieux        setBcc(Address.toHeader(mimeMessage.getRecipients(
4308812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein                com.android.emailcommon.mail.Message.RecipientType.BCC)));
4314d3e937bb3ca208c320e8a124c6f26079c4090d0James Lemieux        setReplyTo(Address.toHeader(mimeMessage.getReplyTo()));
4328812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        subject = mimeMessage.getSubject();
43320dbbd66471f23520fbddf63c5af6a517839f5e8Andrew Sapperstein
43420dbbd66471f23520fbddf63c5af6a517839f5e8Andrew Sapperstein        final Date sentDate = mimeMessage.getSentDate();
43520dbbd66471f23520fbddf63c5af6a517839f5e8Andrew Sapperstein        final Date internalDate = mimeMessage.getInternalDate();
43620dbbd66471f23520fbddf63c5af6a517839f5e8Andrew Sapperstein        if (sentDate != null) {
43720dbbd66471f23520fbddf63c5af6a517839f5e8Andrew Sapperstein            dateReceivedMs = sentDate.getTime();
43820dbbd66471f23520fbddf63c5af6a517839f5e8Andrew Sapperstein        } else if (internalDate != null) {
43920dbbd66471f23520fbddf63c5af6a517839f5e8Andrew Sapperstein            dateReceivedMs = internalDate.getTime();
44020dbbd66471f23520fbddf63c5af6a517839f5e8Andrew Sapperstein        } else {
44120dbbd66471f23520fbddf63c5af6a517839f5e8Andrew Sapperstein            dateReceivedMs = System.currentTimeMillis();
44220dbbd66471f23520fbddf63c5af6a517839f5e8Andrew Sapperstein        }
4438812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
4448812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        // for now, always set defaults
4458812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        alwaysShowImages = false;
4468812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        viaDomain = null;
4478812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        draftType = UIProvider.DraftType.NOT_A_DRAFT;
4486a2df258316b267151296556dbbdba20200ecb1fJin Cao        sendingState = UIProvider.ConversationSendingState.OTHER;
4498812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        starred = false;
4508812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        spamWarningString = null;
4518812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        messageFlags = 0;
452f59d01c3116dc2adde97a5b52aa6094144c2d315Andrew Sapperstein        clipped = false;
45320c2082e85e87dc9c70b3d74e20ed31d3eff7364Andrew Sapperstein        permalink = null;
4548812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        hasAttachments = false;
4558812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
4568812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        // body values (snippet/bodyText/bodyHtml)
4578812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        // Now process body parts & attachments
4588812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        ArrayList<Part> viewables = new ArrayList<Part>();
4598812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        ArrayList<Part> attachments = new ArrayList<Part>();
4608812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        MimeUtility.collectParts(mimeMessage, viewables, attachments);
4618812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
462934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux        ConversionUtilities.BodyFieldData data = ConversionUtilities.parseBodyFields(viewables);
4638812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
4648812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        snippet = data.snippet;
4658812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein        bodyText = data.textContent;
46627a36a6bbeebb6cfd53ad2766463d71ab4b26ce0James Lemieux
46727a36a6bbeebb6cfd53ad2766463d71ab4b26ce0James Lemieux        // sanitize the HTML found within the .eml file before consuming it
46827a36a6bbeebb6cfd53ad2766463d71ab4b26ce0James Lemieux        bodyHtml = HtmlSanitizer.sanitizeHtml(data.htmlContent);
4697434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein
4707434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein        // populate mAttachments
4717434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein        mAttachments = Lists.newArrayList();
4727434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein
4737434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein        final String messageId = mimeMessage.getMessageId();
474934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux
475934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux        int partId = 0;
4767434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein        for (final Part attachmentPart : attachments) {
4777434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein            mAttachments.add(new Attachment(context, attachmentPart,
4788e1ffbf042a23824a97a9f47cfc81cf6f14603beJames Lemieux                    emlFileUri, messageId, Integer.toString(partId++), false /* inline */));
479934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux        }
480934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux
481934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux        // instantiating an Attachment for each viewable will cause it to be registered within the
482934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux        // EmlAttachmentProvider for later access when displaying inline attachments
483934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux        for (final Part viewablePart : viewables) {
484934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            final String[] cids = viewablePart.getHeader(MimeHeader.HEADER_CONTENT_ID);
485934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            if (cids != null && cids.length == 1) {
486934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux                final String cid = REMOVE_OPTIONAL_BRACKETS.matcher(cids[0]).replaceAll("$1");
4878e1ffbf042a23824a97a9f47cfc81cf6f14603beJames Lemieux                mAttachments.add(new Attachment(context, viewablePart, emlFileUri, messageId, cid,
4888e1ffbf042a23824a97a9f47cfc81cf6f14603beJames Lemieux                        true /* inline */));
489934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux            }
4907434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein        }
4917434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein
4927434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein        hasAttachments = !mAttachments.isEmpty();
4937434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein
494934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux        attachmentListUri = hasAttachments ?
4957434e800d4313a227120ca36bd95683752a7879fAndrew Sapperstein                EmlAttachmentProvider.getAttachmentsListUri(emlFileUri, messageId) : null;
496934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux
497934b1f470a646a4ca64fc63eeb823d4c5c12698eJames Lemieux        attachmentByCidUri = EmlAttachmentProvider.getAttachmentByCidUri(emlFileUri, messageId);
4988812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein    }
4998812d3c50e35c4f2a02d29c35c76082c4ebec0cdAndrew Sapperstein
500a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang    public boolean isFlaggedReplied() {
501a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang        return (messageFlags & UIProvider.MessageFlags.REPLIED) ==
502a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang                UIProvider.MessageFlags.REPLIED;
503a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang    }
504a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang
505a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang    public boolean isFlaggedForwarded() {
506a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang        return (messageFlags & UIProvider.MessageFlags.FORWARDED) ==
507a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang                UIProvider.MessageFlags.FORWARDED;
508a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang    }
509a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang
510a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang    public boolean isFlaggedCalendarInvite() {
511a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang        return (messageFlags & UIProvider.MessageFlags.CALENDAR_INVITE) ==
512a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang                UIProvider.MessageFlags.CALENDAR_INVITE;
513a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang    }
514a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang
5158960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    public String getFrom() {
5168960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        return mFrom;
5178960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    }
5188960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy
5198960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    public synchronized void setFrom(final String from) {
5208960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mFrom = from;
5218960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mFromAddresses = null;
5228960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    }
5238960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy
5248960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    public String getTo() {
5258960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        return mTo;
5268960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    }
5278960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy
5288960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    public synchronized void setTo(final String to) {
5298960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mTo = to;
5308960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mToAddresses = null;
5318960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    }
5328960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy
5338960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    public String getCc() {
5348960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        return mCc;
5358960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    }
5368960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy
5378960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    public synchronized void setCc(final String cc) {
5388960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mCc = cc;
5398960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mCcAddresses = null;
5408960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    }
5418960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy
5428960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    public String getBcc() {
5438960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        return mBcc;
5448960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    }
5458960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy
5468960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    public synchronized void setBcc(final String bcc) {
5478960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mBcc = bcc;
5488960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mBccAddresses = null;
5498960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    }
5508960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy
5512bae2f5ef13424f8d932f5e45a2e276b531ecfe6Martin Hibdon    @VisibleForTesting
5528960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    public String getReplyTo() {
5538960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        return mReplyTo;
5548960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    }
5558960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy
5568960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    public synchronized void setReplyTo(final String replyTo) {
5578960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mReplyTo = replyTo;
5588960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy        mReplyToAddresses = null;
5598960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy    }
5608960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy
561d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein    public synchronized String[] getFromAddresses() {
562d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein        if (mFromAddresses == null) {
5638960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy            mFromAddresses = tokenizeAddresses(mFrom);
564d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein        }
565d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein        return mFromAddresses;
566d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein    }
567d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein
5689016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    public String[] getFromAddressesUnescaped() {
5699016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler        return unescapeAddresses(getFromAddresses());
5709016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    }
5719016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler
572bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    public synchronized String[] getToAddresses() {
573bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        if (mToAddresses == null) {
5748960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy            mToAddresses = tokenizeAddresses(mTo);
575bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        }
576bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        return mToAddresses;
577bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    }
578bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook
5799016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    public String[] getToAddressesUnescaped() {
5809016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler        return unescapeAddresses(getToAddresses());
5819016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    }
5829016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler
583bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    public synchronized String[] getCcAddresses() {
584bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        if (mCcAddresses == null) {
5858960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy            mCcAddresses = tokenizeAddresses(mCc);
586bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        }
587bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        return mCcAddresses;
588bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    }
589bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook
5909016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    public String[] getCcAddressesUnescaped() {
5919016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler        return unescapeAddresses(getCcAddresses());
5929016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    }
5939016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler
594bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    public synchronized String[] getBccAddresses() {
595bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        if (mBccAddresses == null) {
5968960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy            mBccAddresses = tokenizeAddresses(mBcc);
597bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        }
598bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        return mBccAddresses;
599bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    }
600bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook
6019016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    public String[] getBccAddressesUnescaped() {
6029016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler        return unescapeAddresses(getBccAddresses());
6039016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    }
6049016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler
605bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    public synchronized String[] getReplyToAddresses() {
606bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        if (mReplyToAddresses == null) {
6078960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy            mReplyToAddresses = tokenizeAddresses(mReplyTo);
608bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        }
609bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook        return mReplyToAddresses;
610bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook    }
6113233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang
6129016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    public String[] getReplyToAddressesUnescaped() {
6139016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler        return unescapeAddresses(getReplyToAddresses());
6149016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    }
6159016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler
6169016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    private static String[] unescapeAddresses(String[] escaped) {
6179016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler        final String[] unescaped = new String[escaped.length];
6189016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler        for (int i = 0; i < escaped.length; i++) {
6199016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler            final String escapeMore = escaped[i].replace("<", "&lt;").replace(">", "&gt;");
6209016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler            unescaped[i] = Html.fromHtml(escapeMore).toString();
6219016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler        }
6229016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler        return unescaped;
6239016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler    }
6249016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler
625233f562368e4e3af9ca86b16d1b0a151df6157eaPaul Westbrook    public static String[] tokenizeAddresses(String addresses) {
6265ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp        if (TextUtils.isEmpty(addresses)) {
6275ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp            return new String[0];
6285ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp        }
6299016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler
630845f87e34179bcbb2862c09572576ab775be472dmindyp        Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(addresses);
6315ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp        String[] strings = new String[tokens.length];
6325ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp        for (int i = 0; i < tokens.length;i++) {
6335ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp            strings[i] = tokens[i].toString();
6345ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp        }
6355ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp        return strings;
6365ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp    }
6376766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang
6386766b6e5468d2f1935587b3bc1f8e65be94cd6fbAndy Huang    public List<Attachment> getAttachments() {
6399ab47b16e0189d219c16e2eddfbd66c741c01229Andy Huang        if (mAttachments == null) {
6409ab47b16e0189d219c16e2eddfbd66c741c01229Andy Huang            if (attachmentsJson != null) {
6419ab47b16e0189d219c16e2eddfbd66c741c01229Andy Huang                mAttachments = Attachment.fromJSONArray(attachmentsJson);
6429ab47b16e0189d219c16e2eddfbd66c741c01229Andy Huang            } else {
6439ab47b16e0189d219c16e2eddfbd66c741c01229Andy Huang                mAttachments = Collections.emptyList();
6449ab47b16e0189d219c16e2eddfbd66c741c01229Andy Huang            }
6455a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        }
6465a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang        return mAttachments;
6475a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang    }
6485a9290731bf565538a9cf91892346c7a6f4da0ecAndy Huang
6493233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang    /**
6505a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein     * Returns the number of attachments in the message.
6515a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein     * @param includeInline If {@code true}, includes inline attachments in the count.
6525a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein     *                      {@code false}, otherwise.
6535a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein     * @return the number of attachments in the message.
6545a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein     */
6555a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein    public int getAttachmentCount(boolean includeInline) {
6565a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein        // If include inline, just return the full list count.
6575a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein        if (includeInline) {
6585a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein            return mAttachments.size();
6595a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein        }
6605a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein
6615a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein        // Otherwise, iterate through the attachment list,
6625a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein        // skipping inline attachments.
6635a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein        int numAttachments = 0;
6645a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein        final List<Attachment> attachments = getAttachments();
6655a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein        for (int i = 0, size = attachments.size(); i < size; i++) {
6665a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein            if (attachments.get(i).isInlineAttachment()) {
6675a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein                continue;
6685a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein            }
6695a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein            numAttachments++;
6705a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein        }
6715a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein
6725a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein        return numAttachments;
6735a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein    }
6745a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein
6755a5c53d39abfa4d4d79081a450aecb61a6744911Andrew Sapperstein    /**
6763233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     * Returns whether a "Show Pictures" button should initially appear for this message. If the
6773233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     * button is shown, the message must also block all non-local images in the body. Inversely, if
6783233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     * the button is not shown, the message must show all images within (or else the user would be
6793233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     * stuck with no images and no way to reveal them).
6803233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     *
6813233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     * @return true if a "Show Pictures" button should appear.
6823233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     */
6833233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang    public boolean shouldShowImagePrompt() {
684606dbd7a44b8445e872c25c0fe080e3e12a47adfAndrew Sapperstein        return !alwaysShowImages && (embedsExternalResources ||
685606dbd7a44b8445e872c25c0fe080e3e12a47adfAndrew Sapperstein                (!TextUtils.isEmpty(bodyHtml) && INLINE_IMAGE_PATTERN.matcher(bodyHtml).find()));
68641dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook    }
68741dca185f7683b36bdafd9520c0648c897a95834Paul Westbrook
688aa27bc0e1c3bb6be4609b00007637a9d3e960f5eScott Kennedy    @Override
689606dbd7a44b8445e872c25c0fe080e3e12a47adfAndrew Sapperstein    public boolean embedsExternalResources() {
690606dbd7a44b8445e872c25c0fe080e3e12a47adfAndrew Sapperstein        return embedsExternalResources;
6913233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang    }
6923233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang
6933233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang    /**
6943233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     * Helper method to command a provider to mark all messages from this sender with the
6953233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     * {@link MessageColumns#ALWAYS_SHOW_IMAGES} flag set.
6963233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     *
6973233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     * @param handler a caller-provided handler to run the query on
6983233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     * @param token (optional) token to identify the command to the handler
6993233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     * @param cookie (optional) cookie to pass to the handler
7003233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang     */
7013233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang    public void markAlwaysShowImages(AsyncQueryHandler handler, int token, Object cookie) {
702839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang        alwaysShowImages = true;
7033233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang
704d8e249ee7abb0e1ad24e17e4e299736d4a150936Andy Huang        final ContentValues values = new ContentValues(1);
705839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang        values.put(UIProvider.MessageColumns.ALWAYS_SHOW_IMAGES, 1);
706d8e249ee7abb0e1ad24e17e4e299736d4a150936Andy Huang
707d8e249ee7abb0e1ad24e17e4e299736d4a150936Andy Huang        handler.startUpdate(token, cookie, uri, values, null, null);
708d8e249ee7abb0e1ad24e17e4e299736d4a150936Andy Huang    }
709d8e249ee7abb0e1ad24e17e4e299736d4a150936Andy Huang
710aa27bc0e1c3bb6be4609b00007637a9d3e960f5eScott Kennedy    @Override
711014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang    public String getBodyAsHtml() {
712014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang        String body = "";
713014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang        if (!TextUtils.isEmpty(bodyHtml)) {
714014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang            body = bodyHtml;
715014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang        } else if (!TextUtils.isEmpty(bodyText)) {
7168d6e803bf63d5dad5cb0187c82171e42147e8a44Yu Ping Hu            final SpannableString spannable = new SpannableString(bodyText);
717da153fb1651c2f70fbb3a2f9930950faec8b798bYu Ping Hu            Linkify.addLinks(spannable, Linkify.EMAIL_ADDRESSES);
7188d6e803bf63d5dad5cb0187c82171e42147e8a44Yu Ping Hu            body = Html.toHtml(spannable);
719014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang        }
720014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang        return body;
721014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang    }
722014ea4c15d147794789b9c5bf4e243fa08781ad9Andy Huang
723aa27bc0e1c3bb6be4609b00007637a9d3e960f5eScott Kennedy    @Override
724606dbd7a44b8445e872c25c0fe080e3e12a47adfAndrew Sapperstein    public long getId() {
725606dbd7a44b8445e872c25c0fe080e3e12a47adfAndrew Sapperstein        return id;
726606dbd7a44b8445e872c25c0fe080e3e12a47adfAndrew Sapperstein    }
727735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein
728735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein    public boolean isDraft() {
729735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein        return draftType != UIProvider.DraftType.NOT_A_DRAFT;
730735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein    }
7313ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira}
732