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