Home | History | Annotate | Download | only in pdu
      1 /*
      2  * Copyright (C) 2007-2008 Esmertec AG.
      3  * Copyright (C) 2007-2008 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package com.android.messaging.mmslib.pdu;
     19 
     20 import android.net.Uri;
     21 import android.util.SparseArray;
     22 
     23 /**
     24  * The pdu part.
     25  */
     26 public class PduPart {
     27     /**
     28      * Well-Known Parameters.
     29      */
     30     public static final int P_Q                  = 0x80;
     31     public static final int P_CHARSET            = 0x81;
     32     public static final int P_LEVEL              = 0x82;
     33     public static final int P_TYPE               = 0x83;
     34     public static final int P_DEP_NAME           = 0x85;
     35     public static final int P_DEP_FILENAME       = 0x86;
     36     public static final int P_DIFFERENCES        = 0x87;
     37     public static final int P_PADDING            = 0x88;
     38     // This value of "TYPE" s used with Content-Type: multipart/related
     39     public static final int P_CT_MR_TYPE         = 0x89;
     40     public static final int P_DEP_START          = 0x8A;
     41     public static final int P_DEP_START_INFO     = 0x8B;
     42     public static final int P_DEP_COMMENT        = 0x8C;
     43     public static final int P_DEP_DOMAIN         = 0x8D;
     44     public static final int P_MAX_AGE            = 0x8E;
     45     public static final int P_DEP_PATH           = 0x8F;
     46     public static final int P_SECURE             = 0x90;
     47     public static final int P_SEC                = 0x91;
     48     public static final int P_MAC                = 0x92;
     49     public static final int P_CREATION_DATE      = 0x93;
     50     public static final int P_MODIFICATION_DATE  = 0x94;
     51     public static final int P_READ_DATE          = 0x95;
     52     public static final int P_SIZE               = 0x96;
     53     public static final int P_NAME               = 0x97;
     54     public static final int P_FILENAME           = 0x98;
     55     public static final int P_START              = 0x99;
     56     public static final int P_START_INFO         = 0x9A;
     57     public static final int P_COMMENT            = 0x9B;
     58     public static final int P_DOMAIN             = 0x9C;
     59     public static final int P_PATH               = 0x9D;
     60 
     61     /**
     62      * Header field names.
     63      */
     64      public static final int P_CONTENT_TYPE       = 0x91;
     65      public static final int P_CONTENT_LOCATION   = 0x8E;
     66      public static final int P_CONTENT_ID         = 0xC0;
     67      public static final int P_DEP_CONTENT_DISPOSITION = 0xAE;
     68      public static final int P_CONTENT_DISPOSITION = 0xC5;
     69     // The next header is unassigned header, use reserved header(0x48) value.
     70     public static final int P_CONTENT_TRANSFER_ENCODING = 0xC8;
     71 
     72     /**
     73      * Content=Transfer-Encoding string.
     74      */
     75     public static final String CONTENT_TRANSFER_ENCODING =
     76             "Content-Transfer-Encoding";
     77 
     78     /**
     79      * Value of Content-Transfer-Encoding.
     80      */
     81     public static final String P_BINARY = "binary";
     82     public static final String P_7BIT = "7bit";
     83     public static final String P_8BIT = "8bit";
     84     public static final String P_BASE64 = "base64";
     85     public static final String P_QUOTED_PRINTABLE = "quoted-printable";
     86 
     87     /**
     88      * Value of disposition can be set to PduPart when the value is octet in
     89      * the PDU.
     90      * "from-data" instead of Form-data<Octet 128>.
     91      * "attachment" instead of Attachment<Octet 129>.
     92      * "inline" instead of Inline<Octet 130>.
     93      */
     94     static final byte[] DISPOSITION_FROM_DATA = "from-data".getBytes();
     95     static final byte[] DISPOSITION_ATTACHMENT = "attachment".getBytes();
     96     static final byte[] DISPOSITION_INLINE = "inline".getBytes();
     97 
     98     /**
     99      * Content-Disposition value.
    100      */
    101     public static final int P_DISPOSITION_FROM_DATA = 0x80;
    102     public static final int P_DISPOSITION_ATTACHMENT = 0x81;
    103     public static final int P_DISPOSITION_INLINE = 0x82;
    104 
    105     /**
    106      * Header of part.
    107      */
    108     private SparseArray<Object> mPartHeader = null;
    109 
    110     /**
    111      * Data uri.
    112      */
    113     private Uri mUri = null;
    114 
    115     /**
    116      * Part data.
    117      */
    118     private byte[] mPartData = null;
    119 
    120     private static final String TAG = "PduPart";
    121 
    122     /**
    123      * Empty Constructor.
    124      */
    125     public PduPart() {
    126         mPartHeader = new SparseArray<Object>();
    127     }
    128 
    129     /**
    130      * Set part data. The data are stored as byte array.
    131      *
    132      * @param data the data
    133      */
    134     public void setData(final byte[] data) {
    135         mPartData = data;
    136     }
    137 
    138     /**
    139      * @return The part data or null if the data wasn't set or
    140      * the data is stored as Uri.
    141      * @see #getDataUri
    142      */
    143     public byte[] getData() {
    144         return mPartData;
    145     }
    146 
    147     /**
    148      * Set data uri. The data are stored as Uri.
    149      *
    150      * @param uri the uri
    151      */
    152     public void setDataUri(final Uri uri) {
    153         mUri = uri;
    154     }
    155 
    156     /**
    157      * @return The Uri of the part data or null if the data wasn't set or
    158      * the data is stored as byte array.
    159      * @see #getData
    160      */
    161     public Uri getDataUri() {
    162         return mUri;
    163     }
    164 
    165     /**
    166      * Set Content-id value
    167      *
    168      * @param contentId the content-id value
    169      * @throws NullPointerException if the value is null.
    170      */
    171     public void setContentId(final byte[] contentId) {
    172         if ((contentId == null) || (contentId.length == 0)) {
    173             throw new IllegalArgumentException(
    174                     "Content-Id may not be null or empty.");
    175         }
    176 
    177         if ((contentId.length > 1)
    178                 && ((char) contentId[0] == '<')
    179                 && ((char) contentId[contentId.length - 1] == '>')) {
    180             mPartHeader.put(P_CONTENT_ID, contentId);
    181             return;
    182         }
    183 
    184         // Insert beginning '<' and trailing '>' for Content-Id.
    185         final byte[] buffer = new byte[contentId.length + 2];
    186         buffer[0] = (byte) (0xff & '<');
    187         buffer[buffer.length - 1] = (byte) (0xff & '>');
    188         System.arraycopy(contentId, 0, buffer, 1, contentId.length);
    189         mPartHeader.put(P_CONTENT_ID, buffer);
    190     }
    191 
    192     /**
    193      * Get Content-id value.
    194      *
    195      * @return the value
    196      */
    197     public byte[] getContentId() {
    198         return (byte[]) mPartHeader.get(P_CONTENT_ID);
    199     }
    200 
    201     /**
    202      * Set Char-set value.
    203      *
    204      * @param charset the value
    205      */
    206     public void setCharset(final int charset) {
    207         mPartHeader.put(P_CHARSET, charset);
    208     }
    209 
    210     /**
    211      * Get Char-set value
    212      *
    213      * @return the charset value. Return 0 if charset was not set.
    214      */
    215     public int getCharset() {
    216         final Integer charset = (Integer) mPartHeader.get(P_CHARSET);
    217         if (charset == null) {
    218             return 0;
    219         } else {
    220             return charset.intValue();
    221         }
    222     }
    223 
    224     /**
    225      * Set Content-Location value.
    226      *
    227      * @param contentLocation the value
    228      * @throws NullPointerException if the value is null.
    229      */
    230     public void setContentLocation(final byte[] contentLocation) {
    231         if (contentLocation == null) {
    232             throw new NullPointerException("null content-location");
    233         }
    234 
    235         mPartHeader.put(P_CONTENT_LOCATION, contentLocation);
    236     }
    237 
    238     /**
    239      * Get Content-Location value.
    240      *
    241      * @return the value
    242      * return PduPart.disposition[0] instead of <Octet 128> (Form-data).
    243      * return PduPart.disposition[1] instead of <Octet 129> (Attachment).
    244      * return PduPart.disposition[2] instead of <Octet 130> (Inline).
    245      */
    246     public byte[] getContentLocation() {
    247         return (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
    248     }
    249 
    250     /**
    251      * Set Content-Disposition value.
    252      * Use PduPart.disposition[0] instead of <Octet 128> (Form-data).
    253      * Use PduPart.disposition[1] instead of <Octet 129> (Attachment).
    254      * Use PduPart.disposition[2] instead of <Octet 130> (Inline).
    255      *
    256      * @param contentDisposition the value
    257      * @throws NullPointerException if the value is null.
    258      */
    259     public void setContentDisposition(final byte[] contentDisposition) {
    260         if (contentDisposition == null) {
    261             throw new NullPointerException("null content-disposition");
    262         }
    263 
    264         mPartHeader.put(P_CONTENT_DISPOSITION, contentDisposition);
    265     }
    266 
    267     /**
    268      * Get Content-Disposition value.
    269      *
    270      * @return the value
    271      */
    272     public byte[] getContentDisposition() {
    273         return (byte[]) mPartHeader.get(P_CONTENT_DISPOSITION);
    274     }
    275 
    276     /**
    277      * Set Content-Type value.
    278      *
    279      * @param value the value
    280      * @throws NullPointerException if the value is null.
    281      */
    282     public void setContentType(final byte[] contentType) {
    283         if (contentType == null) {
    284             throw new NullPointerException("null content-type");
    285         }
    286 
    287         mPartHeader.put(P_CONTENT_TYPE, contentType);
    288     }
    289 
    290     /**
    291      * Get Content-Type value of part.
    292      *
    293      * @return the value
    294      */
    295     public byte[] getContentType() {
    296         return (byte[]) mPartHeader.get(P_CONTENT_TYPE);
    297     }
    298 
    299     /**
    300      * Set Content-Transfer-Encoding value
    301      *
    302      * @param contentId the content-id value
    303      * @throws NullPointerException if the value is null.
    304      */
    305     public void setContentTransferEncoding(final byte[] contentTransferEncoding) {
    306         if (contentTransferEncoding == null) {
    307             throw new NullPointerException("null content-transfer-encoding");
    308         }
    309 
    310         mPartHeader.put(P_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
    311     }
    312 
    313     /**
    314      * Get Content-Transfer-Encoding value.
    315      *
    316      * @return the value
    317      */
    318     public byte[] getContentTransferEncoding() {
    319         return (byte[]) mPartHeader.get(P_CONTENT_TRANSFER_ENCODING);
    320     }
    321 
    322     /**
    323      * Set Content-type parameter: name.
    324      *
    325      * @param name the name value
    326      * @throws NullPointerException if the value is null.
    327      */
    328     public void setName(final byte[] name) {
    329         if (null == name) {
    330             throw new NullPointerException("null content-id");
    331         }
    332 
    333         mPartHeader.put(P_NAME, name);
    334     }
    335 
    336     /**
    337      * Get content-type parameter: name.
    338      *
    339      * @return the name
    340      */
    341     public byte[] getName() {
    342         return (byte[]) mPartHeader.get(P_NAME);
    343     }
    344 
    345     /**
    346      * Get Content-disposition parameter: filename
    347      *
    348      * @param fileName the filename value
    349      * @throws NullPointerException if the value is null.
    350      */
    351     public void setFilename(final byte[] fileName) {
    352         if (null == fileName) {
    353             throw new NullPointerException("null content-id");
    354         }
    355 
    356         mPartHeader.put(P_FILENAME, fileName);
    357     }
    358 
    359     /**
    360      * Set Content-disposition parameter: filename
    361      *
    362      * @return the filename
    363      */
    364     public byte[] getFilename() {
    365         return (byte[]) mPartHeader.get(P_FILENAME);
    366     }
    367 
    368     public String generateLocation() {
    369         // Assumption: At least one of the content-location / name / filename
    370         // or content-id should be set. This is guaranteed by the PduParser
    371         // for incoming messages and by MM composer for outgoing messages.
    372         byte[] location = (byte[]) mPartHeader.get(P_NAME);
    373         if (null == location) {
    374             location = (byte[]) mPartHeader.get(P_FILENAME);
    375 
    376             if (null == location) {
    377                 location = (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
    378             }
    379         }
    380 
    381         if (null == location) {
    382             final byte[] contentId = (byte[]) mPartHeader.get(P_CONTENT_ID);
    383             return "cid:" + new String(contentId);
    384         } else {
    385             return new String(location);
    386         }
    387     }
    388 }
    389 
    390