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.MessagingException; 20 21 import java.io.BufferedWriter; 22 import java.io.IOException; 23 import java.io.OutputStream; 24 import java.io.OutputStreamWriter; 25 import java.util.ArrayList; 26 27 public class MimeHeader { 28 /** 29 * Application specific header that contains Store specific information about an attachment. 30 * In IMAP this contains the IMAP BODYSTRUCTURE part id so that the ImapStore can later 31 * retrieve the attachment at will from the server. 32 * The info is recorded from this header on LocalStore.appendMessages and is put back 33 * into the MIME data by LocalStore.fetch. 34 */ 35 public static final String HEADER_ANDROID_ATTACHMENT_STORE_DATA = "X-Android-Attachment-StoreData"; 36 /** 37 * Application specific header that is used to tag body parts for quoted/forwarded messages. 38 */ 39 public static final String HEADER_ANDROID_BODY_QUOTED_PART = "X-Android-Body-Quoted-Part"; 40 41 public static final String HEADER_CONTENT_TYPE = "Content-Type"; 42 public static final String HEADER_CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding"; 43 public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition"; 44 public static final String HEADER_CONTENT_ID = "Content-ID"; 45 46 /** 47 * Fields that should be omitted when writing the header using writeTo() 48 */ 49 private static final String[] WRITE_OMIT_FIELDS = { 50 // HEADER_ANDROID_ATTACHMENT_DOWNLOADED, 51 // HEADER_ANDROID_ATTACHMENT_ID, 52 HEADER_ANDROID_ATTACHMENT_STORE_DATA 53 }; 54 55 protected final ArrayList<Field> mFields = new ArrayList<Field>(); 56 57 public void clear() { 58 mFields.clear(); 59 } 60 61 public String getFirstHeader(String name) throws MessagingException { 62 String[] header = getHeader(name); 63 if (header == null) { 64 return null; 65 } 66 return header[0]; 67 } 68 69 public void addHeader(String name, String value) throws MessagingException { 70 mFields.add(new Field(name, value)); 71 } 72 73 public void setHeader(String name, String value) throws MessagingException { 74 if (name == null || value == null) { 75 return; 76 } 77 removeHeader(name); 78 addHeader(name, value); 79 } 80 81 public String[] getHeader(String name) throws MessagingException { 82 ArrayList<String> values = new ArrayList<String>(); 83 for (Field field : mFields) { 84 if (field.name.equalsIgnoreCase(name)) { 85 values.add(field.value); 86 } 87 } 88 if (values.size() == 0) { 89 return null; 90 } 91 return values.toArray(new String[] {}); 92 } 93 94 public void removeHeader(String name) throws MessagingException { 95 ArrayList<Field> removeFields = new ArrayList<Field>(); 96 for (Field field : mFields) { 97 if (field.name.equalsIgnoreCase(name)) { 98 removeFields.add(field); 99 } 100 } 101 mFields.removeAll(removeFields); 102 } 103 104 /** 105 * Write header into String 106 * 107 * @return CR-NL separated header string except the headers in writeOmitFields 108 * null if header is empty 109 */ 110 public String writeToString() { 111 if (mFields.size() == 0) { 112 return null; 113 } 114 StringBuilder builder = new StringBuilder(); 115 for (Field field : mFields) { 116 if (!arrayContains(WRITE_OMIT_FIELDS, field.name)) { 117 builder.append(field.name + ": " + field.value + "\r\n"); 118 } 119 } 120 return builder.toString(); 121 } 122 123 public void writeTo(OutputStream out) throws IOException, MessagingException { 124 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024); 125 for (Field field : mFields) { 126 if (!arrayContains(WRITE_OMIT_FIELDS, field.name)) { 127 writer.write(field.name + ": " + field.value + "\r\n"); 128 } 129 } 130 writer.flush(); 131 } 132 133 private static class Field { 134 final String name; 135 final String value; 136 137 public Field(String name, String value) { 138 this.name = name; 139 this.value = value; 140 } 141 142 @Override 143 public String toString() { 144 return name + "=" + value; 145 } 146 } 147 148 @Override 149 public String toString() { 150 return (mFields == null) ? null : mFields.toString(); 151 } 152 153 public final static boolean arrayContains(Object[] a, Object o) { 154 int index = arrayIndex(a, o); 155 return (index >= 0); 156 } 157 158 public final static int arrayIndex(Object[] a, Object o) { 159 for (int i = 0, count = a.length; i < count; i++) { 160 if (a[i].equals(o)) { 161 return i; 162 } 163 } 164 return -1; 165 } 166 } 167