diff options
Diffstat (limited to 'java/com/android/voicemailomtp/src/org/apache/james/mime4j/BodyDescriptor.java')
-rw-r--r-- | java/com/android/voicemailomtp/src/org/apache/james/mime4j/BodyDescriptor.java | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/java/com/android/voicemailomtp/src/org/apache/james/mime4j/BodyDescriptor.java b/java/com/android/voicemailomtp/src/org/apache/james/mime4j/BodyDescriptor.java new file mode 100644 index 000000000..867c43d86 --- /dev/null +++ b/java/com/android/voicemailomtp/src/org/apache/james/mime4j/BodyDescriptor.java @@ -0,0 +1,392 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.mime4j; + +import java.util.HashMap; +import java.util.Map; + +/** + * Encapsulates the values of the MIME-specific header fields + * (which starts with <code>Content-</code>). + * + * + * @version $Id: BodyDescriptor.java,v 1.4 2005/02/11 10:08:37 ntherning Exp $ + */ +public class BodyDescriptor { + private static Log log = LogFactory.getLog(BodyDescriptor.class); + + private String mimeType = "text/plain"; + private String boundary = null; + private String charset = "us-ascii"; + private String transferEncoding = "7bit"; + private Map<String, String> parameters = new HashMap<String, String>(); + private boolean contentTypeSet = false; + private boolean contentTransferEncSet = false; + + /** + * Creates a new root <code>BodyDescriptor</code> instance. + */ + public BodyDescriptor() { + this(null); + } + + /** + * Creates a new <code>BodyDescriptor</code> instance. + * + * @param parent the descriptor of the parent or <code>null</code> if this + * is the root descriptor. + */ + public BodyDescriptor(BodyDescriptor parent) { + if (parent != null && parent.isMimeType("multipart/digest")) { + mimeType = "message/rfc822"; + } else { + mimeType = "text/plain"; + } + } + + /** + * Should be called for each <code>Content-</code> header field of + * a MIME message or part. + * + * @param name the field name. + * @param value the field value. + */ + public void addField(String name, String value) { + + name = name.trim().toLowerCase(); + + if (name.equals("content-transfer-encoding") && !contentTransferEncSet) { + contentTransferEncSet = true; + + value = value.trim().toLowerCase(); + if (value.length() > 0) { + transferEncoding = value; + } + + } else if (name.equals("content-type") && !contentTypeSet) { + contentTypeSet = true; + + value = value.trim(); + + /* + * Unfold Content-Type value + */ + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (c == '\r' || c == '\n') { + continue; + } + sb.append(c); + } + + Map<String, String> params = getHeaderParams(sb.toString()); + + String main = params.get(""); + if (main != null) { + main = main.toLowerCase().trim(); + int index = main.indexOf('/'); + boolean valid = false; + if (index != -1) { + String type = main.substring(0, index).trim(); + String subtype = main.substring(index + 1).trim(); + if (type.length() > 0 && subtype.length() > 0) { + main = type + "/" + subtype; + valid = true; + } + } + + if (!valid) { + main = null; + } + } + String b = params.get("boundary"); + + if (main != null + && ((main.startsWith("multipart/") && b != null) + || !main.startsWith("multipart/"))) { + + mimeType = main; + } + + if (isMultipart()) { + boundary = b; + } + + String c = params.get("charset"); + if (c != null) { + c = c.trim(); + if (c.length() > 0) { + charset = c.toLowerCase(); + } + } + + /* + * Add all other parameters to parameters. + */ + parameters.putAll(params); + parameters.remove(""); + parameters.remove("boundary"); + parameters.remove("charset"); + } + } + + private Map<String, String> getHeaderParams(String headerValue) { + Map<String, String> result = new HashMap<String, String>(); + + // split main value and parameters + String main; + String rest; + if (headerValue.indexOf(";") == -1) { + main = headerValue; + rest = null; + } else { + main = headerValue.substring(0, headerValue.indexOf(";")); + rest = headerValue.substring(main.length() + 1); + } + + result.put("", main); + if (rest != null) { + char[] chars = rest.toCharArray(); + StringBuffer paramName = new StringBuffer(); + StringBuffer paramValue = new StringBuffer(); + + final byte READY_FOR_NAME = 0; + final byte IN_NAME = 1; + final byte READY_FOR_VALUE = 2; + final byte IN_VALUE = 3; + final byte IN_QUOTED_VALUE = 4; + final byte VALUE_DONE = 5; + final byte ERROR = 99; + + byte state = READY_FOR_NAME; + boolean escaped = false; + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + + switch (state) { + case ERROR: + if (c == ';') + state = READY_FOR_NAME; + break; + + case READY_FOR_NAME: + if (c == '=') { + log.error("Expected header param name, got '='"); + state = ERROR; + break; + } + + paramName = new StringBuffer(); + paramValue = new StringBuffer(); + + state = IN_NAME; + // $FALL-THROUGH$ + + case IN_NAME: + if (c == '=') { + if (paramName.length() == 0) + state = ERROR; + else + state = READY_FOR_VALUE; + break; + } + + // not '='... just add to name + paramName.append(c); + break; + + case READY_FOR_VALUE: + boolean fallThrough = false; + switch (c) { + case ' ': + case '\t': + break; // ignore spaces, especially before '"' + + case '"': + state = IN_QUOTED_VALUE; + break; + + default: + state = IN_VALUE; + fallThrough = true; + break; + } + if (!fallThrough) + break; + + // $FALL-THROUGH$ + + case IN_VALUE: + fallThrough = false; + switch (c) { + case ';': + case ' ': + case '\t': + result.put( + paramName.toString().trim().toLowerCase(), + paramValue.toString().trim()); + state = VALUE_DONE; + fallThrough = true; + break; + default: + paramValue.append(c); + break; + } + if (!fallThrough) + break; + + // $FALL-THROUGH$ + + case VALUE_DONE: + switch (c) { + case ';': + state = READY_FOR_NAME; + break; + + case ' ': + case '\t': + break; + + default: + state = ERROR; + break; + } + break; + + case IN_QUOTED_VALUE: + switch (c) { + case '"': + if (!escaped) { + // don't trim quoted strings; the spaces could be intentional. + result.put( + paramName.toString().trim().toLowerCase(), + paramValue.toString()); + state = VALUE_DONE; + } else { + escaped = false; + paramValue.append(c); + } + break; + + case '\\': + if (escaped) { + paramValue.append('\\'); + } + escaped = !escaped; + break; + + default: + if (escaped) { + paramValue.append('\\'); + } + escaped = false; + paramValue.append(c); + break; + } + break; + + } + } + + // done looping. check if anything is left over. + if (state == IN_VALUE) { + result.put( + paramName.toString().trim().toLowerCase(), + paramValue.toString().trim()); + } + } + + return result; + } + + + public boolean isMimeType(String mimeType) { + return this.mimeType.equals(mimeType.toLowerCase()); + } + + /** + * Return true if the BodyDescriptor belongs to a message + */ + public boolean isMessage() { + return mimeType.equals("message/rfc822"); + } + + /** + * Return true if the BodyDescripotro belongs to a multipart + */ + public boolean isMultipart() { + return mimeType.startsWith("multipart/"); + } + + /** + * Return the MimeType + */ + public String getMimeType() { + return mimeType; + } + + /** + * Return the boundary + */ + public String getBoundary() { + return boundary; + } + + /** + * Return the charset + */ + public String getCharset() { + return charset; + } + + /** + * Return all parameters for the BodyDescriptor + */ + public Map<String, String> getParameters() { + return parameters; + } + + /** + * Return the TransferEncoding + */ + public String getTransferEncoding() { + return transferEncoding; + } + + /** + * Return true if it's base64 encoded + */ + public boolean isBase64Encoded() { + return "base64".equals(transferEncoding); + } + + /** + * Return true if it's quoted-printable + */ + public boolean isQuotedPrintableEncoded() { + return "quoted-printable".equals(transferEncoding); + } + + @Override + public String toString() { + return mimeType; + } +}
\ No newline at end of file |