1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.emailcommon.utility;
18
19import com.android.emailcommon.internet.MimeHeader;
20import com.android.emailcommon.internet.MimeUtility;
21import com.android.emailcommon.mail.MessagingException;
22import com.android.emailcommon.mail.Part;
23
24import android.text.TextUtils;
25
26import java.util.ArrayList;
27
28public class ConversionUtilities {
29    /**
30     * Values for HEADER_ANDROID_BODY_QUOTED_PART to tag body parts
31     */
32    public static final String BODY_QUOTED_PART_REPLY = "quoted-reply";
33    public static final String BODY_QUOTED_PART_FORWARD = "quoted-forward";
34    public static final String BODY_QUOTED_PART_INTRO = "quoted-intro";
35
36    /**
37     * Helper function to append text to a StringBuffer, creating it if necessary.
38     * Optimization:  The majority of the time we are *not* appending - we should have a path
39     * that deals with single strings.
40     */
41    private static StringBuffer appendTextPart(StringBuffer sb, String newText) {
42        if (newText == null) {
43            return sb;
44        }
45        else if (sb == null) {
46            sb = new StringBuffer(newText);
47        } else {
48            if (sb.length() > 0) {
49                sb.append('\n');
50            }
51            sb.append(newText);
52        }
53        return sb;
54    }
55
56    /**
57     * Plain-Old-Data class to return parsed body data from
58     * {@link ConversionUtilities#parseBodyFields}
59     */
60    public static class BodyFieldData {
61        public String textContent;
62        public String htmlContent;
63        public String textReply;
64        public String htmlReply;
65        public String introText;
66        public String snippet;
67        public boolean isQuotedReply;
68        public boolean isQuotedForward;
69    }
70
71    /**
72     * Parse body text (plain and/or HTML) from MimeMessage to {@link BodyFieldData}.
73     */
74    public static BodyFieldData parseBodyFields(ArrayList<Part> viewables)
75    throws MessagingException {
76        final BodyFieldData data = new BodyFieldData();
77        StringBuffer sbHtml = null;
78        StringBuffer sbText = null;
79        StringBuffer sbHtmlReply = null;
80        StringBuffer sbTextReply = null;
81        StringBuffer sbIntroText = null;
82
83        for (Part viewable : viewables) {
84            String text = MimeUtility.getTextFromPart(viewable);
85            String[] replyTags = viewable.getHeader(MimeHeader.HEADER_ANDROID_BODY_QUOTED_PART);
86            String replyTag = null;
87            if (replyTags != null && replyTags.length > 0) {
88                replyTag = replyTags[0];
89            }
90            // Deploy text as marked by the various tags
91            boolean isHtml = "text/html".equalsIgnoreCase(viewable.getMimeType());
92
93            if (replyTag != null) {
94                data.isQuotedReply = BODY_QUOTED_PART_REPLY.equalsIgnoreCase(replyTag);
95                data.isQuotedForward = BODY_QUOTED_PART_FORWARD.equalsIgnoreCase(replyTag);
96                boolean isQuotedIntro = BODY_QUOTED_PART_INTRO.equalsIgnoreCase(replyTag);
97
98                if (data.isQuotedReply || data.isQuotedForward) {
99                    if (isHtml) {
100                        sbHtmlReply = appendTextPart(sbHtmlReply, text);
101                    } else {
102                        sbTextReply = appendTextPart(sbTextReply, text);
103                    }
104                    continue;
105                }
106                if (isQuotedIntro) {
107                    sbIntroText = appendTextPart(sbIntroText, text);
108                    continue;
109                }
110            }
111
112            // Most of the time, just process regular body parts
113            if (isHtml) {
114                sbHtml = appendTextPart(sbHtml, text);
115            } else {
116                sbText = appendTextPart(sbText, text);
117            }
118        }
119
120        // write the combined data to the body part
121        if (!TextUtils.isEmpty(sbText)) {
122            String text = sbText.toString();
123            data.textContent = text;
124            data.snippet = TextUtilities.makeSnippetFromPlainText(text);
125        }
126        if (!TextUtils.isEmpty(sbHtml)) {
127            String text = sbHtml.toString();
128            data.htmlContent = text;
129            if (data.snippet == null) {
130                data.snippet = TextUtilities.makeSnippetFromHtmlText(text);
131            }
132        }
133        if (sbHtmlReply != null && sbHtmlReply.length() != 0) {
134            data.htmlReply = sbHtmlReply.toString();
135        }
136        if (sbTextReply != null && sbTextReply.length() != 0) {
137            data.textReply = sbTextReply.toString();
138        }
139        if (sbIntroText != null && sbIntroText.length() != 0) {
140            data.introText = sbIntroText.toString();
141        }
142        return data;
143    }
144}
145