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