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.field; 21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.regex.Matcher; 23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.regex.Pattern; 24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/** 26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * The base class of all field classes. 27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @version $Id: Field.java,v 1.6 2004/10/25 07:26:46 ntherning Exp $ 30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpublic abstract class Field { 32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String SENDER = "Sender"; 33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String FROM = "From"; 34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String TO = "To"; 35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String CC = "Cc"; 36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String BCC = "Bcc"; 37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String REPLY_TO = "Reply-To"; 38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String RESENT_SENDER = "Resent-Sender"; 39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String RESENT_FROM = "Resent-From"; 40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String RESENT_TO = "Resent-To"; 41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String RESENT_CC = "Resent-Cc"; 42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String RESENT_BCC = "Resent-Bcc"; 43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String DATE = "Date"; 45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String RESENT_DATE = "Resent-Date"; 46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String SUBJECT = "Subject"; 48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String CONTENT_TYPE = "Content-Type"; 49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static final String CONTENT_TRANSFER_ENCODING = 50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook "Content-Transfer-Encoding"; 51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private static final String FIELD_NAME_PATTERN = 53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook "^([\\x21-\\x39\\x3b-\\x7e]+)[ \t]*:"; 54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private static final Pattern fieldNamePattern = 55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook Pattern.compile(FIELD_NAME_PATTERN); 56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private static final DefaultFieldParser parser = new DefaultFieldParser(); 58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private final String name; 60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private final String body; 61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private final String raw; 62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook protected Field(final String name, final String body, final String raw) { 64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook this.name = name; 65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook this.body = body; 66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook this.raw = raw; 67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Parses the given string and returns an instance of the 71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <code>Field</code> class. The type of the class returned depends on 72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * the field name: 73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <table> 74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <tr> 75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <td><em>Field name</em></td><td><em>Class returned</em></td> 76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <td>Content-Type</td><td>org.apache.james.mime4j.field.ContentTypeField</td> 77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <td>other</td><td>org.apache.james.mime4j.field.UnstructuredField</td> 78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * </tr> 79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * </table> 80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @param s the string to parse. 82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return a <code>Field</code> instance. 83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @throws IllegalArgumentException on parse errors. 84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static Field parse(final String raw) { 86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /* 88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unfold the field. 89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook final String unfolded = raw.replaceAll("\r|\n", ""); 91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /* 93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Split into name and value. 94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook final Matcher fieldMatcher = fieldNamePattern.matcher(unfolded); 96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook if (!fieldMatcher.find()) { 97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook throw new IllegalArgumentException("Invalid field in string"); 98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook final String name = fieldMatcher.group(1); 100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook String body = unfolded.substring(fieldMatcher.end()); 102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook if (body.length() > 0 && body.charAt(0) == ' ') { 103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook body = body.substring(1); 104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return parser.parse(name, body, raw); 107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Gets the default parser used to parse fields. 111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the default field parser 112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public static DefaultFieldParser getParser() { 114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return parser; 115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Gets the name of the field (<code>Subject</code>, 119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <code>From</code>, etc). 120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the field name. 122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public String getName() { 124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return name; 125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Gets the original raw field string. 129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the original raw field string. 131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public String getRaw() { 133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return raw; 134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Gets the unfolded, unparsed and possibly encoded (see RFC 2047) field 138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * body string. 139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the unfolded unparsed field body string. 141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public String getBody() { 143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return body; 144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Determines if this is a <code>Content-Type</code> field. 148bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 149bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return <code>true</code> if this is a <code>Content-Type</code> field, 150bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <code>false</code> otherwise. 151bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 152bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public boolean isContentType() { 153bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return CONTENT_TYPE.equalsIgnoreCase(name); 154bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 155bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 156bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 157bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Determines if this is a <code>Subject</code> field. 158bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 159bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return <code>true</code> if this is a <code>Subject</code> field, 160bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <code>false</code> otherwise. 161bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 162bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public boolean isSubject() { 163bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return SUBJECT.equalsIgnoreCase(name); 164bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 165bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 166bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 167bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Determines if this is a <code>From</code> field. 168bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 169bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return <code>true</code> if this is a <code>From</code> field, 170bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <code>false</code> otherwise. 171bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 172bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public boolean isFrom() { 173bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return FROM.equalsIgnoreCase(name); 174bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 175bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 176bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 177bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Determines if this is a <code>To</code> field. 178bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 179bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return <code>true</code> if this is a <code>To</code> field, 180bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <code>false</code> otherwise. 181bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 182bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public boolean isTo() { 183bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return TO.equalsIgnoreCase(name); 184bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 185bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 186bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 187bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @see #getRaw() 188bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 189bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public String toString() { 190bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return raw; 191bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 192bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook} 193