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       * Set data uri. The data are stored as Uri.
    162       *
    163       * @param uri the uri
    164       */
    165      public void setDataUri(Uri uri) {
    166          mUri = uri;
    167      }
    168 
    169      /**
    170       * @return The Uri of the part data or null if the data wasn't set or
    171       *         the data is stored as byte array.
    172       * @see #getData
    173       */
    174      public Uri getDataUri() {
    175          return mUri;
    176      }
    177 
    178      /**
    179       * Set Content-id value
    180       *
    181       * @param contentId the content-id value
    182       * @throws NullPointerException if the value is null.
    183       */
    184      public void setContentId(byte[] contentId) {
    185          if((contentId == null) || (contentId.length == 0)) {
    186              throw new IllegalArgumentException(
    187                      "Content-Id may not be null or empty.");
    188          }
    189 
    190          if ((contentId.length > 1)
    191                  && ((char) contentId[0] == '<')
    192                  && ((char) contentId[contentId.length - 1] == '>')) {
    193              mPartHeader.put(P_CONTENT_ID, contentId);
    194              return;
    195          }
    196 
    197          // Insert beginning '<' and trailing '>' for Content-Id.
    198          byte[] buffer = new byte[contentId.length + 2];
    199          buffer[0] = (byte) (0xff & '<');
    200          buffer[buffer.length - 1] = (byte) (0xff & '>');
    201          System.arraycopy(contentId, 0, buffer, 1, contentId.length);
    202          mPartHeader.put(P_CONTENT_ID, buffer);
    203      }
    204 
    205      /**
    206       * Get Content-id value.
    207       *
    208       * @return the value
    209       */
    210      public byte[] getContentId() {
    211          return (byte[]) mPartHeader.get(P_CONTENT_ID);
    212      }
    213 
    214      /**
    215       * Set Char-set value.
    216       *
    217       * @param charset the value
    218       */
    219      public void setCharset(int charset) {
    220          mPartHeader.put(P_CHARSET, charset);
    221      }
    222 
    223      /**
    224       * Get Char-set value
    225       *
    226       * @return the charset value. Return 0 if charset was not set.
    227       */
    228      public int getCharset() {
    229          Integer charset = (Integer) mPartHeader.get(P_CHARSET);
    230          if(charset == null) {
    231              return 0;
    232          } else {
    233              return charset.intValue();
    234          }
    235      }
    236 
    237      /**
    238       * Set Content-Location value.
    239       *
    240       * @param contentLocation the value
    241       * @throws NullPointerException if the value is null.
    242       */
    243      public void setContentLocation(byte[] contentLocation) {
    244          if(contentLocation == null) {
    245              throw new NullPointerException("null content-location");
    246          }
    247 
    248          mPartHeader.put(P_CONTENT_LOCATION, contentLocation);
    249      }
    250 
    251      /**
    252       * Get Content-Location value.
    253       *
    254       * @return the value
    255       *     return PduPart.disposition[0] instead of <Octet 128> (Form-data).
    256       *     return PduPart.disposition[1] instead of <Octet 129> (Attachment).
    257       *     return PduPart.disposition[2] instead of <Octet 130> (Inline).
    258       */
    259      public byte[] getContentLocation() {
    260          return (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
    261      }
    262 
    263      /**
    264       * Set Content-Disposition value.
    265       * Use PduPart.disposition[0] instead of <Octet 128> (Form-data).
    266       * Use PduPart.disposition[1] instead of <Octet 129> (Attachment).
    267       * Use PduPart.disposition[2] instead of <Octet 130> (Inline).
    268       *
    269       * @param contentDisposition the value
    270       * @throws NullPointerException if the value is null.
    271       */
    272      public void setContentDisposition(byte[] contentDisposition) {
    273          if(contentDisposition == null) {
    274              throw new NullPointerException("null content-disposition");
    275          }
    276 
    277          mPartHeader.put(P_CONTENT_DISPOSITION, contentDisposition);
    278      }
    279 
    280      /**
    281       * Get Content-Disposition value.
    282       *
    283       * @return the value
    284       */
    285      public byte[] getContentDisposition() {
    286          return (byte[]) mPartHeader.get(P_CONTENT_DISPOSITION);
    287      }
    288 
    289      /**
    290       *  Set Content-Type value.
    291       *
    292       *  @param value the value
    293       *  @throws NullPointerException if the value is null.
    294       */
    295      public void setContentType(byte[] contentType) {
    296          if(contentType == null) {
    297              throw new NullPointerException("null content-type");
    298          }
    299 
    300          mPartHeader.put(P_CONTENT_TYPE, contentType);
    301      }
    302 
    303      /**
    304       * Get Content-Type value of part.
    305       *
    306       * @return the value
    307       */
    308      public byte[] getContentType() {
    309          return (byte[]) mPartHeader.get(P_CONTENT_TYPE);
    310      }
    311 
    312      /**
    313       * Set Content-Transfer-Encoding value
    314       *
    315       * @param contentId the content-id value
    316       * @throws NullPointerException if the value is null.
    317       */
    318      public void setContentTransferEncoding(byte[] contentTransferEncoding) {
    319          if(contentTransferEncoding == null) {
    320              throw new NullPointerException("null content-transfer-encoding");
    321          }
    322 
    323          mPartHeader.put(P_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
    324      }
    325 
    326      /**
    327       * Get Content-Transfer-Encoding value.
    328       *
    329       * @return the value
    330       */
    331      public byte[] getContentTransferEncoding() {
    332          return (byte[]) mPartHeader.get(P_CONTENT_TRANSFER_ENCODING);
    333      }
    334 
    335      /**
    336       * Set Content-type parameter: name.
    337       *
    338       * @param name the name value
    339       * @throws NullPointerException if the value is null.
    340       */
    341      public void setName(byte[] name) {
    342          if(null == name) {
    343              throw new NullPointerException("null content-id");
    344          }
    345 
    346          mPartHeader.put(P_NAME, name);
    347      }
    348 
    349      /**
    350       *  Get content-type parameter: name.
    351       *
    352       *  @return the name
    353       */
    354      public byte[] getName() {
    355          return (byte[]) mPartHeader.get(P_NAME);
    356      }
    357 
    358      /**
    359       * Get Content-disposition parameter: filename
    360       *
    361       * @param fileName the filename value
    362       * @throws NullPointerException if the value is null.
    363       */
    364      public void setFilename(byte[] fileName) {
    365          if(null == fileName) {
    366              throw new NullPointerException("null content-id");
    367          }
    368 
    369          mPartHeader.put(P_FILENAME, fileName);
    370      }
    371 
    372      /**
    373       * Set Content-disposition parameter: filename
    374       *
    375       * @return the filename
    376       */
    377      public byte[] getFilename() {
    378          return (byte[]) mPartHeader.get(P_FILENAME);
    379      }
    380 
    381     public String generateLocation() {
    382         // Assumption: At least one of the content-location / name / filename
    383         // or content-id should be set. This is guaranteed by the PduParser
    384         // for incoming messages and by MM composer for outgoing messages.
    385         byte[] location = (byte[]) mPartHeader.get(P_NAME);
    386         if(null == location) {
    387             location = (byte[]) mPartHeader.get(P_FILENAME);
    388 
    389             if (null == location) {
    390                 location = (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
    391             }
    392         }
    393 
    394         if (null == location) {
    395             byte[] contentId = (byte[]) mPartHeader.get(P_CONTENT_ID);
    396             return "cid:" + new String(contentId);
    397         } else {
    398             return new String(location);
    399         }
    400     }
    401 }
    402 
    403