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