13f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen/*
23f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * Copyright (C) 2015 The Android Open Source Project
33f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen *
43f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * Licensed under the Apache License, Version 2.0 (the "License");
53f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * you may not use this file except in compliance with the License.
63f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * You may obtain a copy of the License at
73f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen *
83f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen *      http://www.apache.org/licenses/LICENSE-2.0
93f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen *
103f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * Unless required by applicable law or agreed to in writing, software
113f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * distributed under the License is distributed on an "AS IS" BASIS,
123f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * See the License for the specific language governing permissions and
143f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * limitations under the License.
153f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen */
163f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenpackage com.android.phone.common.mail.internet;
173f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
183f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport com.android.phone.common.mail.Body;
193f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport com.android.phone.common.mail.BodyPart;
203f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport com.android.phone.common.mail.MessagingException;
213f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
223f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport java.io.BufferedWriter;
233f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport java.io.IOException;
243f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport java.io.OutputStream;
253f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport java.io.OutputStreamWriter;
263f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport java.util.regex.Pattern;
273f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
283f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen/**
293f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * TODO this is a close approximation of Message, need to update along with
303f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * Message.
313f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen */
323f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenpublic class MimeBodyPart extends BodyPart {
333f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    protected MimeHeader mHeader = new MimeHeader();
343f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    protected MimeHeader mExtendedHeader;
353f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    protected Body mBody;
363f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    protected int mSize;
373f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
383f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    // regex that matches content id surrounded by "<>" optionally.
393f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    private static final Pattern REMOVE_OPTIONAL_BRACKETS = Pattern.compile("^<?([^>]+)>?$");
403f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    // regex that matches end of line.
413f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    private static final Pattern END_OF_LINE = Pattern.compile("\r?\n");
423f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
433f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public MimeBodyPart() throws MessagingException {
443f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        this(null);
453f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
463f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
473f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public MimeBodyPart(Body body) throws MessagingException {
483f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        this(body, null);
493f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
503f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
513f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public MimeBodyPart(Body body, String mimeType) throws MessagingException {
523f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        if (mimeType != null) {
533f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            setHeader(MimeHeader.HEADER_CONTENT_TYPE, mimeType);
543f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        }
553f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        setBody(body);
563f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
573f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
583f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    protected String getFirstHeader(String name) throws MessagingException {
593f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        return mHeader.getFirstHeader(name);
603f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
613f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
623f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
633f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public void addHeader(String name, String value) throws MessagingException {
643f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        mHeader.addHeader(name, value);
653f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
663f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
673f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
683f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public void setHeader(String name, String value) throws MessagingException {
693f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        mHeader.setHeader(name, value);
703f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
713f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
723f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
733f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public String[] getHeader(String name) throws MessagingException {
743f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        return mHeader.getHeader(name);
753f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
763f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
773f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
783f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public void removeHeader(String name) throws MessagingException {
793f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        mHeader.removeHeader(name);
803f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
813f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
823f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
833f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public Body getBody() throws MessagingException {
843f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        return mBody;
853f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
863f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
873f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
883f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public void setBody(Body body) throws MessagingException {
893f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        this.mBody = body;
903f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        if (body instanceof com.android.phone.common.mail.Multipart) {
913f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            com.android.phone.common.mail.Multipart multipart =
923f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen                ((com.android.phone.common.mail.Multipart)body);
933f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            multipart.setParent(this);
943f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            setHeader(MimeHeader.HEADER_CONTENT_TYPE, multipart.getContentType());
953f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        }
963f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        else if (body instanceof TextBody) {
973f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            String contentType = String.format("%s;\n charset=utf-8", getMimeType());
983f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            String name = MimeUtility.getHeaderParameter(getContentType(), "name");
993f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            if (name != null) {
1003f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen                contentType += String.format(";\n name=\"%s\"", name);
1013f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            }
1023f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            setHeader(MimeHeader.HEADER_CONTENT_TYPE, contentType);
1033f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
1043f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        }
1053f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
1063f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
1073f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
1083f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public String getContentType() throws MessagingException {
1093f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        String contentType = getFirstHeader(MimeHeader.HEADER_CONTENT_TYPE);
1103f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        if (contentType == null) {
1113f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            return "text/plain";
1123f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        } else {
1133f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            return contentType;
1143f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        }
1153f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
1163f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
1173f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
1183f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public String getDisposition() throws MessagingException {
1193f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        String contentDisposition = getFirstHeader(MimeHeader.HEADER_CONTENT_DISPOSITION);
1203f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        if (contentDisposition == null) {
1213f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            return null;
1223f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        } else {
1233f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            return contentDisposition;
1243f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        }
1253f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
1263f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
1273f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
1283f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public String getContentId() throws MessagingException {
1293f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        String contentId = getFirstHeader(MimeHeader.HEADER_CONTENT_ID);
1303f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        if (contentId == null) {
1313f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            return null;
1323f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        } else {
1333f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            // remove optionally surrounding brackets.
1343f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            return REMOVE_OPTIONAL_BRACKETS.matcher(contentId).replaceAll("$1");
1353f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        }
1363f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
1373f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
1383f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
1393f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public String getMimeType() throws MessagingException {
1403f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        return MimeUtility.getHeaderParameter(getContentType(), null);
1413f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
1423f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
1433f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
1443f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public boolean isMimeType(String mimeType) throws MessagingException {
1453f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        return getMimeType().equals(mimeType);
1463f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
1473f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
1483f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public void setSize(int size) {
1493f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        this.mSize = size;
1503f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
1513f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
1523f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
1533f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public int getSize() throws MessagingException {
1543f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        return mSize;
1553f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
1563f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
1573f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    /**
1583f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     * Set extended header
1593f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     *
1603f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     * @param name Extended header name
1613f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     * @param value header value - flattened by removing CR-NL if any
1623f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     * remove header if value is null
1633f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     * @throws MessagingException
1643f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     */
1653f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
1663f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public void setExtendedHeader(String name, String value) throws MessagingException {
1673f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        if (value == null) {
1683f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            if (mExtendedHeader != null) {
1693f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen                mExtendedHeader.removeHeader(name);
1703f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            }
1713f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            return;
1723f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        }
1733f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        if (mExtendedHeader == null) {
1743f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            mExtendedHeader = new MimeHeader();
1753f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        }
1763f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        mExtendedHeader.setHeader(name, END_OF_LINE.matcher(value).replaceAll(""));
1773f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
1783f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
1793f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    /**
1803f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     * Get extended header
1813f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     *
1823f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     * @param name Extended header name
1833f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     * @return header value - null if header does not exist
1843f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     * @throws MessagingException
1853f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     */
1863f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
1873f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public String getExtendedHeader(String name) throws MessagingException {
1883f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        if (mExtendedHeader == null) {
1893f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            return null;
1903f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        }
1913f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        return mExtendedHeader.getFirstHeader(name);
1923f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
1933f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen
1943f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    /**
1953f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     * Write the MimeMessage out in MIME format.
1963f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen     */
1973f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    @Override
1983f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    public void writeTo(OutputStream out) throws IOException, MessagingException {
1993f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
2003f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        mHeader.writeTo(out);
2013f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        writer.write("\r\n");
2023f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        writer.flush();
2033f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        if (mBody != null) {
2043f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen            mBody.writeTo(out);
2053f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen        }
2063f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen    }
2073f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen}
208