1 /* 2 * Copyright (C) 2008 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 17 package com.android.emailcommon.internet; 18 19 import com.android.emailcommon.mail.Body; 20 import com.android.emailcommon.mail.BodyPart; 21 import com.android.emailcommon.mail.MessagingException; 22 23 import java.io.BufferedWriter; 24 import java.io.IOException; 25 import java.io.OutputStream; 26 import java.io.OutputStreamWriter; 27 import java.util.regex.Pattern; 28 29 /** 30 * TODO this is a close approximation of Message, need to update along with 31 * Message. 32 */ 33 public class MimeBodyPart extends BodyPart { 34 protected MimeHeader mHeader = new MimeHeader(); 35 protected MimeHeader mExtendedHeader; 36 protected Body mBody; 37 protected int mSize; 38 39 // regex that matches content id surrounded by "<>" optionally. 40 private static final Pattern REMOVE_OPTIONAL_BRACKETS = Pattern.compile("^<?([^>]+)>?$"); 41 // regex that matches end of line. 42 private static final Pattern END_OF_LINE = Pattern.compile("\r?\n"); 43 MimeBodyPart()44 public MimeBodyPart() throws MessagingException { 45 this(null); 46 } 47 MimeBodyPart(Body body)48 public MimeBodyPart(Body body) throws MessagingException { 49 this(body, null); 50 } 51 MimeBodyPart(Body body, String mimeType)52 public MimeBodyPart(Body body, String mimeType) throws MessagingException { 53 if (mimeType != null) { 54 setHeader(MimeHeader.HEADER_CONTENT_TYPE, mimeType); 55 } 56 setBody(body); 57 } 58 getFirstHeader(String name)59 protected String getFirstHeader(String name) throws MessagingException { 60 return mHeader.getFirstHeader(name); 61 } 62 63 @Override addHeader(String name, String value)64 public void addHeader(String name, String value) throws MessagingException { 65 mHeader.addHeader(name, value); 66 } 67 68 @Override setHeader(String name, String value)69 public void setHeader(String name, String value) throws MessagingException { 70 mHeader.setHeader(name, value); 71 } 72 73 @Override getHeader(String name)74 public String[] getHeader(String name) throws MessagingException { 75 return mHeader.getHeader(name); 76 } 77 78 @Override removeHeader(String name)79 public void removeHeader(String name) throws MessagingException { 80 mHeader.removeHeader(name); 81 } 82 83 @Override getBody()84 public Body getBody() throws MessagingException { 85 return mBody; 86 } 87 88 @Override setBody(Body body)89 public void setBody(Body body) throws MessagingException { 90 this.mBody = body; 91 if (body instanceof com.android.emailcommon.mail.Multipart) { 92 com.android.emailcommon.mail.Multipart multipart = 93 ((com.android.emailcommon.mail.Multipart)body); 94 multipart.setParent(this); 95 setHeader(MimeHeader.HEADER_CONTENT_TYPE, multipart.getContentType()); 96 } 97 else if (body instanceof TextBody) { 98 String contentType = String.format("%s;\n charset=utf-8", getMimeType()); 99 String name = MimeUtility.getHeaderParameter(getContentType(), "name"); 100 if (name != null) { 101 contentType += String.format(";\n name=\"%s\"", name); 102 } 103 setHeader(MimeHeader.HEADER_CONTENT_TYPE, contentType); 104 setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64"); 105 } 106 } 107 108 @Override getContentType()109 public String getContentType() throws MessagingException { 110 String contentType = getFirstHeader(MimeHeader.HEADER_CONTENT_TYPE); 111 if (contentType == null) { 112 return "text/plain"; 113 } else { 114 return contentType; 115 } 116 } 117 118 @Override getDisposition()119 public String getDisposition() throws MessagingException { 120 String contentDisposition = getFirstHeader(MimeHeader.HEADER_CONTENT_DISPOSITION); 121 if (contentDisposition == null) { 122 return null; 123 } else { 124 return contentDisposition; 125 } 126 } 127 128 @Override getContentId()129 public String getContentId() throws MessagingException { 130 String contentId = getFirstHeader(MimeHeader.HEADER_CONTENT_ID); 131 if (contentId == null) { 132 return null; 133 } else { 134 // remove optionally surrounding brackets. 135 return REMOVE_OPTIONAL_BRACKETS.matcher(contentId).replaceAll("$1"); 136 } 137 } 138 139 @Override getMimeType()140 public String getMimeType() throws MessagingException { 141 return MimeUtility.getHeaderParameter(getContentType(), null); 142 } 143 144 @Override isMimeType(String mimeType)145 public boolean isMimeType(String mimeType) throws MessagingException { 146 return getMimeType().equals(mimeType); 147 } 148 setSize(int size)149 public void setSize(int size) { 150 this.mSize = size; 151 } 152 153 @Override getSize()154 public int getSize() throws MessagingException { 155 return mSize; 156 } 157 158 /** 159 * Set extended header 160 * 161 * @param name Extended header name 162 * @param value header value - flattened by removing CR-NL if any 163 * remove header if value is null 164 * @throws MessagingException 165 */ 166 @Override setExtendedHeader(String name, String value)167 public void setExtendedHeader(String name, String value) throws MessagingException { 168 if (value == null) { 169 if (mExtendedHeader != null) { 170 mExtendedHeader.removeHeader(name); 171 } 172 return; 173 } 174 if (mExtendedHeader == null) { 175 mExtendedHeader = new MimeHeader(); 176 } 177 mExtendedHeader.setHeader(name, END_OF_LINE.matcher(value).replaceAll("")); 178 } 179 180 /** 181 * Get extended header 182 * 183 * @param name Extended header name 184 * @return header value - null if header does not exist 185 * @throws MessagingException 186 */ 187 @Override getExtendedHeader(String name)188 public String getExtendedHeader(String name) throws MessagingException { 189 if (mExtendedHeader == null) { 190 return null; 191 } 192 return mExtendedHeader.getFirstHeader(name); 193 } 194 195 /** 196 * Write the MimeMessage out in MIME format. 197 */ 198 @Override writeTo(OutputStream out)199 public void writeTo(OutputStream out) throws IOException, MessagingException { 200 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024); 201 mHeader.writeTo(out); 202 writer.write("\r\n"); 203 writer.flush(); 204 if (mBody != null) { 205 mBody.writeTo(out); 206 } 207 } 208 } 209