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