/* * Copyright (C) 2007-2008 Esmertec AG. * Copyright (C) 2007-2008 The Android Open Source Project * * Licensed 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 com.google.android.mms.pdu; import android.net.Uri; import java.util.HashMap; import java.util.Map; /** * The pdu part. */ public class PduPart { /** * Well-Known Parameters. */ public static final int P_Q = 0x80; public static final int P_CHARSET = 0x81; public static final int P_LEVEL = 0x82; public static final int P_TYPE = 0x83; public static final int P_DEP_NAME = 0x85; public static final int P_DEP_FILENAME = 0x86; public static final int P_DIFFERENCES = 0x87; public static final int P_PADDING = 0x88; // This value of "TYPE" s used with Content-Type: multipart/related public static final int P_CT_MR_TYPE = 0x89; public static final int P_DEP_START = 0x8A; public static final int P_DEP_START_INFO = 0x8B; public static final int P_DEP_COMMENT = 0x8C; public static final int P_DEP_DOMAIN = 0x8D; public static final int P_MAX_AGE = 0x8E; public static final int P_DEP_PATH = 0x8F; public static final int P_SECURE = 0x90; public static final int P_SEC = 0x91; public static final int P_MAC = 0x92; public static final int P_CREATION_DATE = 0x93; public static final int P_MODIFICATION_DATE = 0x94; public static final int P_READ_DATE = 0x95; public static final int P_SIZE = 0x96; public static final int P_NAME = 0x97; public static final int P_FILENAME = 0x98; public static final int P_START = 0x99; public static final int P_START_INFO = 0x9A; public static final int P_COMMENT = 0x9B; public static final int P_DOMAIN = 0x9C; public static final int P_PATH = 0x9D; /** * Header field names. */ public static final int P_CONTENT_TYPE = 0x91; public static final int P_CONTENT_LOCATION = 0x8E; public static final int P_CONTENT_ID = 0xC0; public static final int P_DEP_CONTENT_DISPOSITION = 0xAE; public static final int P_CONTENT_DISPOSITION = 0xC5; // The next header is unassigned header, use reserved header(0x48) value. public static final int P_CONTENT_TRANSFER_ENCODING = 0xC8; /** * Content=Transfer-Encoding string. */ public static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding"; /** * Value of Content-Transfer-Encoding. */ public static final String P_BINARY = "binary"; public static final String P_7BIT = "7bit"; public static final String P_8BIT = "8bit"; public static final String P_BASE64 = "base64"; public static final String P_QUOTED_PRINTABLE = "quoted-printable"; /** * Value of disposition can be set to PduPart when the value is octet in * the PDU. * "from-data" instead of Form-data. * "attachment" instead of Attachment. * "inline" instead of Inline. */ static final byte[] DISPOSITION_FROM_DATA = "from-data".getBytes(); static final byte[] DISPOSITION_ATTACHMENT = "attachment".getBytes(); static final byte[] DISPOSITION_INLINE = "inline".getBytes(); /** * Content-Disposition value. */ public static final int P_DISPOSITION_FROM_DATA = 0x80; public static final int P_DISPOSITION_ATTACHMENT = 0x81; public static final int P_DISPOSITION_INLINE = 0x82; /** * Header of part. */ private Map mPartHeader = null; /** * Data uri. */ private Uri mUri = null; /** * Part data. */ private byte[] mPartData = null; private static final String TAG = "PduPart"; /** * Empty Constructor. */ public PduPart() { mPartHeader = new HashMap(); } /** * Set part data. The data are stored as byte array. * * @param data the data */ public void setData(byte[] data) { if(data == null) { return; } mPartData = new byte[data.length]; System.arraycopy(data, 0, mPartData, 0, data.length); } /** * @return A copy of the part data or null if the data wasn't set or * the data is stored as Uri. * @see #getDataUri */ public byte[] getData() { if(mPartData == null) { return null; } byte[] byteArray = new byte[mPartData.length]; System.arraycopy(mPartData, 0, byteArray, 0, mPartData.length); return byteArray; } /** * Set data uri. The data are stored as Uri. * * @param uri the uri */ public void setDataUri(Uri uri) { mUri = uri; } /** * @return The Uri of the part data or null if the data wasn't set or * the data is stored as byte array. * @see #getData */ public Uri getDataUri() { return mUri; } /** * Set Content-id value * * @param contentId the content-id value * @throws NullPointerException if the value is null. */ public void setContentId(byte[] contentId) { if((contentId == null) || (contentId.length == 0)) { throw new IllegalArgumentException( "Content-Id may not be null or empty."); } if ((contentId.length > 1) && ((char) contentId[0] == '<') && ((char) contentId[contentId.length - 1] == '>')) { mPartHeader.put(P_CONTENT_ID, contentId); return; } // Insert beginning '<' and trailing '>' for Content-Id. byte[] buffer = new byte[contentId.length + 2]; buffer[0] = (byte) (0xff & '<'); buffer[buffer.length - 1] = (byte) (0xff & '>'); System.arraycopy(contentId, 0, buffer, 1, contentId.length); mPartHeader.put(P_CONTENT_ID, buffer); } /** * Get Content-id value. * * @return the value */ public byte[] getContentId() { return (byte[]) mPartHeader.get(P_CONTENT_ID); } /** * Set Char-set value. * * @param charset the value */ public void setCharset(int charset) { mPartHeader.put(P_CHARSET, charset); } /** * Get Char-set value * * @return the charset value. Return 0 if charset was not set. */ public int getCharset() { Integer charset = (Integer) mPartHeader.get(P_CHARSET); if(charset == null) { return 0; } else { return charset.intValue(); } } /** * Set Content-Location value. * * @param contentLocation the value * @throws NullPointerException if the value is null. */ public void setContentLocation(byte[] contentLocation) { if(contentLocation == null) { throw new NullPointerException("null content-location"); } mPartHeader.put(P_CONTENT_LOCATION, contentLocation); } /** * Get Content-Location value. * * @return the value * return PduPart.disposition[0] instead of (Form-data). * return PduPart.disposition[1] instead of (Attachment). * return PduPart.disposition[2] instead of (Inline). */ public byte[] getContentLocation() { return (byte[]) mPartHeader.get(P_CONTENT_LOCATION); } /** * Set Content-Disposition value. * Use PduPart.disposition[0] instead of (Form-data). * Use PduPart.disposition[1] instead of (Attachment). * Use PduPart.disposition[2] instead of (Inline). * * @param contentDisposition the value * @throws NullPointerException if the value is null. */ public void setContentDisposition(byte[] contentDisposition) { if(contentDisposition == null) { throw new NullPointerException("null content-disposition"); } mPartHeader.put(P_CONTENT_DISPOSITION, contentDisposition); } /** * Get Content-Disposition value. * * @return the value */ public byte[] getContentDisposition() { return (byte[]) mPartHeader.get(P_CONTENT_DISPOSITION); } /** * Set Content-Type value. * * @param value the value * @throws NullPointerException if the value is null. */ public void setContentType(byte[] contentType) { if(contentType == null) { throw new NullPointerException("null content-type"); } mPartHeader.put(P_CONTENT_TYPE, contentType); } /** * Get Content-Type value of part. * * @return the value */ public byte[] getContentType() { return (byte[]) mPartHeader.get(P_CONTENT_TYPE); } /** * Set Content-Transfer-Encoding value * * @param contentId the content-id value * @throws NullPointerException if the value is null. */ public void setContentTransferEncoding(byte[] contentTransferEncoding) { if(contentTransferEncoding == null) { throw new NullPointerException("null content-transfer-encoding"); } mPartHeader.put(P_CONTENT_TRANSFER_ENCODING, contentTransferEncoding); } /** * Get Content-Transfer-Encoding value. * * @return the value */ public byte[] getContentTransferEncoding() { return (byte[]) mPartHeader.get(P_CONTENT_TRANSFER_ENCODING); } /** * Set Content-type parameter: name. * * @param name the name value * @throws NullPointerException if the value is null. */ public void setName(byte[] name) { if(null == name) { throw new NullPointerException("null content-id"); } mPartHeader.put(P_NAME, name); } /** * Get content-type parameter: name. * * @return the name */ public byte[] getName() { return (byte[]) mPartHeader.get(P_NAME); } /** * Get Content-disposition parameter: filename * * @param fileName the filename value * @throws NullPointerException if the value is null. */ public void setFilename(byte[] fileName) { if(null == fileName) { throw new NullPointerException("null content-id"); } mPartHeader.put(P_FILENAME, fileName); } /** * Set Content-disposition parameter: filename * * @return the filename */ public byte[] getFilename() { return (byte[]) mPartHeader.get(P_FILENAME); } public String generateLocation() { // Assumption: At least one of the content-location / name / filename // or content-id should be set. This is guaranteed by the PduParser // for incoming messages and by MM composer for outgoing messages. byte[] location = (byte[]) mPartHeader.get(P_NAME); if(null == location) { location = (byte[]) mPartHeader.get(P_FILENAME); if (null == location) { location = (byte[]) mPartHeader.get(P_CONTENT_LOCATION); } } if (null == location) { byte[] contentId = (byte[]) mPartHeader.get(P_CONTENT_ID); return "cid:" + new String(contentId); } else { return new String(location); } } }