| /* |
| * 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.compat.annotation.UnsupportedAppUsage; |
| 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<Octet 128>. |
| * "attachment" instead of Attachment<Octet 129>. |
| * "inline" instead of Inline<Octet 130>. |
| */ |
| 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<Integer, Object> mPartHeader = null; |
| |
| /** |
| * Data uri. |
| */ |
| private Uri mUri = null; |
| |
| /** |
| * Part data. |
| */ |
| private byte[] mPartData = null; |
| |
| private static final String TAG = "PduPart"; |
| |
| /** |
| * Empty Constructor. |
| */ |
| @UnsupportedAppUsage |
| public PduPart() { |
| mPartHeader = new HashMap<Integer, Object>(); |
| } |
| |
| /** |
| * Set part data. The data are stored as byte array. |
| * |
| * @param data the data |
| */ |
| @UnsupportedAppUsage |
| 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 |
| */ |
| @UnsupportedAppUsage |
| public byte[] getData() { |
| if(mPartData == null) { |
| return null; |
| } |
| |
| byte[] byteArray = new byte[mPartData.length]; |
| System.arraycopy(mPartData, 0, byteArray, 0, mPartData.length); |
| return byteArray; |
| } |
| |
| /** |
| * @return The length of the data, if this object have data, else 0. |
| */ |
| @UnsupportedAppUsage |
| public int getDataLength() { |
| if(mPartData != null){ |
| return mPartData.length; |
| } else { |
| return 0; |
| } |
| } |
| |
| |
| /** |
| * Set data uri. The data are stored as Uri. |
| * |
| * @param uri the uri |
| */ |
| @UnsupportedAppUsage |
| 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 |
| */ |
| @UnsupportedAppUsage |
| public Uri getDataUri() { |
| return mUri; |
| } |
| |
| /** |
| * Set Content-id value |
| * |
| * @param contentId the content-id value |
| * @throws NullPointerException if the value is null. |
| */ |
| @UnsupportedAppUsage |
| 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 |
| */ |
| @UnsupportedAppUsage |
| public byte[] getContentId() { |
| return (byte[]) mPartHeader.get(P_CONTENT_ID); |
| } |
| |
| /** |
| * Set Char-set value. |
| * |
| * @param charset the value |
| */ |
| @UnsupportedAppUsage |
| 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. |
| */ |
| @UnsupportedAppUsage |
| 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. |
| */ |
| @UnsupportedAppUsage |
| 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 <Octet 128> (Form-data). |
| * return PduPart.disposition[1] instead of <Octet 129> (Attachment). |
| * return PduPart.disposition[2] instead of <Octet 130> (Inline). |
| */ |
| @UnsupportedAppUsage |
| public byte[] getContentLocation() { |
| return (byte[]) mPartHeader.get(P_CONTENT_LOCATION); |
| } |
| |
| /** |
| * Set Content-Disposition value. |
| * Use PduPart.disposition[0] instead of <Octet 128> (Form-data). |
| * Use PduPart.disposition[1] instead of <Octet 129> (Attachment). |
| * Use PduPart.disposition[2] instead of <Octet 130> (Inline). |
| * |
| * @param contentDisposition the value |
| * @throws NullPointerException if the value is null. |
| */ |
| @UnsupportedAppUsage |
| 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 |
| */ |
| @UnsupportedAppUsage |
| 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. |
| */ |
| @UnsupportedAppUsage |
| 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 |
| */ |
| @UnsupportedAppUsage |
| 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. |
| */ |
| @UnsupportedAppUsage |
| 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 |
| */ |
| @UnsupportedAppUsage |
| 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. |
| */ |
| @UnsupportedAppUsage |
| 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 |
| */ |
| @UnsupportedAppUsage |
| 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. |
| */ |
| @UnsupportedAppUsage |
| 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 |
| */ |
| @UnsupportedAppUsage |
| public byte[] getFilename() { |
| return (byte[]) mPartHeader.get(P_FILENAME); |
| } |
| |
| @UnsupportedAppUsage |
| 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); |
| } |
| } |
| } |
| |