1d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen/**************************************************************** 2d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Licensed to the Apache Software Foundation (ASF) under one * 3d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * or more contributor license agreements. See the NOTICE file * 4d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * distributed with this work for additional information * 5d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * regarding copyright ownership. The ASF licenses this file * 6d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * to you under the Apache License, Version 2.0 (the * 7d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * "License"); you may not use this file except in compliance * 8d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * with the License. You may obtain a copy of the License at * 9d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * * 10d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * http://www.apache.org/licenses/LICENSE-2.0 * 11d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * * 12d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Unless required by applicable law or agreed to in writing, * 13d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * software distributed under the License is distributed on an * 14d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 15d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * KIND, either express or implied. See the License for the * 16d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * specific language governing permissions and limitations * 17d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * under the License. * 18d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ****************************************************************/ 19d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 20d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenpackage org.apache.james.mime4j; 21d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 22d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport java.util.HashMap; 23d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport java.util.Map; 24d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 25d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen/** 26d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Encapsulates the values of the MIME-specific header fields 27d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * (which starts with <code>Content-</code>). 28d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * 29d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * 30d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * @version $Id: BodyDescriptor.java,v 1.4 2005/02/11 10:08:37 ntherning Exp $ 31d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 32d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenpublic class BodyDescriptor { 33d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private static Log log = LogFactory.getLog(BodyDescriptor.class); 34d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 35d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private String mimeType = "text/plain"; 36d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private String boundary = null; 37d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private String charset = "us-ascii"; 38d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private String transferEncoding = "7bit"; 39d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private Map<String, String> parameters = new HashMap<String, String>(); 40d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private boolean contentTypeSet = false; 41d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private boolean contentTransferEncSet = false; 42d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 43d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 44d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Creates a new root <code>BodyDescriptor</code> instance. 45d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 46d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public BodyDescriptor() { 47d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen this(null); 48d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 49d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 50d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 51d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Creates a new <code>BodyDescriptor</code> instance. 52d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * 53d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * @param parent the descriptor of the parent or <code>null</code> if this 54d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * is the root descriptor. 55d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 56d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public BodyDescriptor(BodyDescriptor parent) { 57d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (parent != null && parent.isMimeType("multipart/digest")) { 58d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen mimeType = "message/rfc822"; 59d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } else { 60d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen mimeType = "text/plain"; 61d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 62d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 63d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 64d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 65d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Should be called for each <code>Content-</code> header field of 66d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * a MIME message or part. 67d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * 68d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * @param name the field name. 69d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * @param value the field value. 70d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 71d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public void addField(String name, String value) { 72d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 73d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen name = name.trim().toLowerCase(); 74d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 75d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (name.equals("content-transfer-encoding") && !contentTransferEncSet) { 76d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen contentTransferEncSet = true; 77d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 78d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen value = value.trim().toLowerCase(); 79d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (value.length() > 0) { 80d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen transferEncoding = value; 81d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 82d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 83d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } else if (name.equals("content-type") && !contentTypeSet) { 84d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen contentTypeSet = true; 85d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 86d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen value = value.trim(); 87d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 88d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /* 89d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Unfold Content-Type value 90d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 91d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen StringBuffer sb = new StringBuffer(); 92d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen for (int i = 0; i < value.length(); i++) { 93d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen char c = value.charAt(i); 94d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (c == '\r' || c == '\n') { 95d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen continue; 96d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 97d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen sb.append(c); 98d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 99d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 100d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Map<String, String> params = getHeaderParams(sb.toString()); 101d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 102d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen String main = params.get(""); 103d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (main != null) { 104d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen main = main.toLowerCase().trim(); 105d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen int index = main.indexOf('/'); 106d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen boolean valid = false; 107d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (index != -1) { 108d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen String type = main.substring(0, index).trim(); 109d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen String subtype = main.substring(index + 1).trim(); 110d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (type.length() > 0 && subtype.length() > 0) { 111d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen main = type + "/" + subtype; 112d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen valid = true; 113d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 114d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 115d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 116d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (!valid) { 117d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen main = null; 118d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 119d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 120d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen String b = params.get("boundary"); 121d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 122d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (main != null 123d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen && ((main.startsWith("multipart/") && b != null) 124d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen || !main.startsWith("multipart/"))) { 125d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 126d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen mimeType = main; 127d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 128d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 129d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (isMultipart()) { 130d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen boundary = b; 131d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 132d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 133d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen String c = params.get("charset"); 134d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (c != null) { 135d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen c = c.trim(); 136d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (c.length() > 0) { 137d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen charset = c.toLowerCase(); 138d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 139d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 140d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 141d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /* 142d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Add all other parameters to parameters. 143d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 144d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen parameters.putAll(params); 145d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen parameters.remove(""); 146d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen parameters.remove("boundary"); 147d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen parameters.remove("charset"); 148d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 149d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 150d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 151d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private Map<String, String> getHeaderParams(String headerValue) { 152d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Map<String, String> result = new HashMap<String, String>(); 153d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 154d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen // split main value and parameters 155d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen String main; 156d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen String rest; 157d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (headerValue.indexOf(";") == -1) { 158d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen main = headerValue; 159d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen rest = null; 160d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } else { 161d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen main = headerValue.substring(0, headerValue.indexOf(";")); 162d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen rest = headerValue.substring(main.length() + 1); 163d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 164d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 165d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen result.put("", main); 166d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (rest != null) { 167d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen char[] chars = rest.toCharArray(); 168d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen StringBuffer paramName = new StringBuffer(); 169d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen StringBuffer paramValue = new StringBuffer(); 170d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 171d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen final byte READY_FOR_NAME = 0; 172d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen final byte IN_NAME = 1; 173d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen final byte READY_FOR_VALUE = 2; 174d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen final byte IN_VALUE = 3; 175d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen final byte IN_QUOTED_VALUE = 4; 176d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen final byte VALUE_DONE = 5; 177d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen final byte ERROR = 99; 178d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 179d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen byte state = READY_FOR_NAME; 180d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen boolean escaped = false; 181d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen for (int i = 0; i < chars.length; i++) { 182d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen char c = chars[i]; 183d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 184d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen switch (state) { 185d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case ERROR: 186d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (c == ';') 187d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen state = READY_FOR_NAME; 188d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 189d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 190d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case READY_FOR_NAME: 191d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (c == '=') { 192d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen log.error("Expected header param name, got '='"); 193d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen state = ERROR; 194d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 195d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 196d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 197d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramName = new StringBuffer(); 198d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramValue = new StringBuffer(); 199d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 200d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen state = IN_NAME; 201d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen // $FALL-THROUGH$ 202d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 203d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case IN_NAME: 204d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (c == '=') { 205d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (paramName.length() == 0) 206d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen state = ERROR; 207d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else 208d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen state = READY_FOR_VALUE; 209d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 210d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 211d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 212d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen // not '='... just add to name 213d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramName.append(c); 214d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 215d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 216d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case READY_FOR_VALUE: 217d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen boolean fallThrough = false; 218d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen switch (c) { 219d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case ' ': 220d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case '\t': 221d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; // ignore spaces, especially before '"' 222d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 223d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case '"': 224d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen state = IN_QUOTED_VALUE; 225d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 226d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 227d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen default: 228d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen state = IN_VALUE; 229d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen fallThrough = true; 230d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 231d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 232d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (!fallThrough) 233d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 234d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 235d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen // $FALL-THROUGH$ 236d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 237d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case IN_VALUE: 238d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen fallThrough = false; 239d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen switch (c) { 240d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case ';': 241d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case ' ': 242d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case '\t': 243d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen result.put( 244d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramName.toString().trim().toLowerCase(), 245d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramValue.toString().trim()); 246d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen state = VALUE_DONE; 247d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen fallThrough = true; 248d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 249d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen default: 250d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramValue.append(c); 251d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 252d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 253d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (!fallThrough) 254d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 255d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 256d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen // $FALL-THROUGH$ 257d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 258d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case VALUE_DONE: 259d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen switch (c) { 260d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case ';': 261d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen state = READY_FOR_NAME; 262d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 263d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 264d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case ' ': 265d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case '\t': 266d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 267d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 268d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen default: 269d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen state = ERROR; 270d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 271d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 272d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 273d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 274d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case IN_QUOTED_VALUE: 275d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen switch (c) { 276d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case '"': 277d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (!escaped) { 278d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen // don't trim quoted strings; the spaces could be intentional. 279d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen result.put( 280d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramName.toString().trim().toLowerCase(), 281d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramValue.toString()); 282d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen state = VALUE_DONE; 283d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } else { 284d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen escaped = false; 285d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramValue.append(c); 286d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 287d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 288d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 289d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen case '\\': 290d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (escaped) { 291d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramValue.append('\\'); 292d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 293d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen escaped = !escaped; 294d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 295d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 296d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen default: 297d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (escaped) { 298d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramValue.append('\\'); 299d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 300d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen escaped = false; 301d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramValue.append(c); 302d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 303d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 304d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen break; 305d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 306d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 307d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 308d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 309d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen // done looping. check if anything is left over. 310d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (state == IN_VALUE) { 311d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen result.put( 312d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramName.toString().trim().toLowerCase(), 313d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen paramValue.toString().trim()); 314d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 315d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 316d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 317d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return result; 318d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 319d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 320d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 321d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public boolean isMimeType(String mimeType) { 322d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return this.mimeType.equals(mimeType.toLowerCase()); 323d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 324d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 325d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 326d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Return true if the BodyDescriptor belongs to a message 327d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 328d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public boolean isMessage() { 329d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return mimeType.equals("message/rfc822"); 330d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 331d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 332d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 333d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Return true if the BodyDescripotro belongs to a multipart 334d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 335d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public boolean isMultipart() { 336d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return mimeType.startsWith("multipart/"); 337d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 338d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 339d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 340d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Return the MimeType 341d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 342d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public String getMimeType() { 343d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return mimeType; 344d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 345d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 346d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 347d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Return the boundary 348d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 349d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public String getBoundary() { 350d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return boundary; 351d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 352d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 353d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 354d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Return the charset 355d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 356d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public String getCharset() { 357d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return charset; 358d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 359d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 360d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 361d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Return all parameters for the BodyDescriptor 362d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 363d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public Map<String, String> getParameters() { 364d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return parameters; 365d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 366d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 367d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 368d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Return the TransferEncoding 369d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 370d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public String getTransferEncoding() { 371d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return transferEncoding; 372d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 373d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 374d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 375d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Return true if it's base64 encoded 376d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 377d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public boolean isBase64Encoded() { 378d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return "base64".equals(transferEncoding); 379d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 380d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 381d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen /** 382d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Return true if it's quoted-printable 383d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 384d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public boolean isQuotedPrintableEncoded() { 385d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return "quoted-printable".equals(transferEncoding); 386d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 387d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 388d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen @Override 389d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public String toString() { 390d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return mimeType; 391d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 392d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen}