Home | History | Annotate | Download | only in pdu
      1 /*
      2  * Copyright (C) 2007 Esmertec AG.
      3  * Copyright (C) 2007 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.util.SparseArray;
     21 
     22 import com.android.messaging.mmslib.InvalidHeaderValueException;
     23 
     24 import java.util.ArrayList;
     25 
     26 public class PduHeaders {
     27     /**
     28      * All pdu header fields.
     29      */
     30     public static final int BCC                             = 0x81;
     31     public static final int CC                              = 0x82;
     32     public static final int CONTENT_LOCATION                = 0x83;
     33     public static final int CONTENT_TYPE                    = 0x84;
     34     public static final int DATE                            = 0x85;
     35     public static final int DELIVERY_REPORT                 = 0x86;
     36     public static final int DELIVERY_TIME                   = 0x87;
     37     public static final int EXPIRY                          = 0x88;
     38     public static final int FROM                            = 0x89;
     39     public static final int MESSAGE_CLASS                   = 0x8A;
     40     public static final int MESSAGE_ID                      = 0x8B;
     41     public static final int MESSAGE_TYPE                    = 0x8C;
     42     public static final int MMS_VERSION                     = 0x8D;
     43     public static final int MESSAGE_SIZE                    = 0x8E;
     44     public static final int PRIORITY                        = 0x8F;
     45 
     46     public static final int READ_REPLY                      = 0x90;
     47     public static final int READ_REPORT                     = 0x90;
     48     public static final int REPORT_ALLOWED                  = 0x91;
     49     public static final int RESPONSE_STATUS                 = 0x92;
     50     public static final int RESPONSE_TEXT                   = 0x93;
     51     public static final int SENDER_VISIBILITY               = 0x94;
     52     public static final int STATUS                          = 0x95;
     53     public static final int SUBJECT                         = 0x96;
     54     public static final int TO                              = 0x97;
     55     public static final int TRANSACTION_ID                  = 0x98;
     56     public static final int RETRIEVE_STATUS                 = 0x99;
     57     public static final int RETRIEVE_TEXT                   = 0x9A;
     58     public static final int READ_STATUS                     = 0x9B;
     59     public static final int REPLY_CHARGING                  = 0x9C;
     60     public static final int REPLY_CHARGING_DEADLINE         = 0x9D;
     61     public static final int REPLY_CHARGING_ID               = 0x9E;
     62     public static final int REPLY_CHARGING_SIZE             = 0x9F;
     63 
     64     public static final int PREVIOUSLY_SENT_BY              = 0xA0;
     65     public static final int PREVIOUSLY_SENT_DATE            = 0xA1;
     66     public static final int STORE                           = 0xA2;
     67     public static final int MM_STATE                        = 0xA3;
     68     public static final int MM_FLAGS                        = 0xA4;
     69     public static final int STORE_STATUS                    = 0xA5;
     70     public static final int STORE_STATUS_TEXT               = 0xA6;
     71     public static final int STORED                          = 0xA7;
     72     public static final int ATTRIBUTES                      = 0xA8;
     73     public static final int TOTALS                          = 0xA9;
     74     public static final int MBOX_TOTALS                     = 0xAA;
     75     public static final int QUOTAS                          = 0xAB;
     76     public static final int MBOX_QUOTAS                     = 0xAC;
     77     public static final int MESSAGE_COUNT                   = 0xAD;
     78     public static final int CONTENT                         = 0xAE;
     79     public static final int START                           = 0xAF;
     80 
     81     public static final int ADDITIONAL_HEADERS              = 0xB0;
     82     public static final int DISTRIBUTION_INDICATOR          = 0xB1;
     83     public static final int ELEMENT_DESCRIPTOR              = 0xB2;
     84     public static final int LIMIT                           = 0xB3;
     85     public static final int RECOMMENDED_RETRIEVAL_MODE      = 0xB4;
     86     public static final int RECOMMENDED_RETRIEVAL_MODE_TEXT = 0xB5;
     87     public static final int STATUS_TEXT                     = 0xB6;
     88     public static final int APPLIC_ID                       = 0xB7;
     89     public static final int REPLY_APPLIC_ID                 = 0xB8;
     90     public static final int AUX_APPLIC_ID                   = 0xB9;
     91     public static final int CONTENT_CLASS                   = 0xBA;
     92     public static final int DRM_CONTENT                     = 0xBB;
     93     public static final int ADAPTATION_ALLOWED              = 0xBC;
     94     public static final int REPLACE_ID                      = 0xBD;
     95     public static final int CANCEL_ID                       = 0xBE;
     96     public static final int CANCEL_STATUS                   = 0xBF;
     97 
     98     /**
     99      * X-Mms-Message-Type field types.
    100      */
    101     public static final int MESSAGE_TYPE_SEND_REQ           = 0x80;
    102     public static final int MESSAGE_TYPE_SEND_CONF          = 0x81;
    103     public static final int MESSAGE_TYPE_NOTIFICATION_IND   = 0x82;
    104     public static final int MESSAGE_TYPE_NOTIFYRESP_IND     = 0x83;
    105     public static final int MESSAGE_TYPE_RETRIEVE_CONF      = 0x84;
    106     public static final int MESSAGE_TYPE_ACKNOWLEDGE_IND    = 0x85;
    107     public static final int MESSAGE_TYPE_DELIVERY_IND       = 0x86;
    108     public static final int MESSAGE_TYPE_READ_REC_IND       = 0x87;
    109     public static final int MESSAGE_TYPE_READ_ORIG_IND      = 0x88;
    110     public static final int MESSAGE_TYPE_FORWARD_REQ        = 0x89;
    111     public static final int MESSAGE_TYPE_FORWARD_CONF       = 0x8A;
    112     public static final int MESSAGE_TYPE_MBOX_STORE_REQ     = 0x8B;
    113     public static final int MESSAGE_TYPE_MBOX_STORE_CONF    = 0x8C;
    114     public static final int MESSAGE_TYPE_MBOX_VIEW_REQ      = 0x8D;
    115     public static final int MESSAGE_TYPE_MBOX_VIEW_CONF     = 0x8E;
    116     public static final int MESSAGE_TYPE_MBOX_UPLOAD_REQ    = 0x8F;
    117     public static final int MESSAGE_TYPE_MBOX_UPLOAD_CONF   = 0x90;
    118     public static final int MESSAGE_TYPE_MBOX_DELETE_REQ    = 0x91;
    119     public static final int MESSAGE_TYPE_MBOX_DELETE_CONF   = 0x92;
    120     public static final int MESSAGE_TYPE_MBOX_DESCR         = 0x93;
    121     public static final int MESSAGE_TYPE_DELETE_REQ         = 0x94;
    122     public static final int MESSAGE_TYPE_DELETE_CONF        = 0x95;
    123     public static final int MESSAGE_TYPE_CANCEL_REQ         = 0x96;
    124     public static final int MESSAGE_TYPE_CANCEL_CONF        = 0x97;
    125 
    126     /**
    127      * X-Mms-Delivery-Report |
    128      * X-Mms-Read-Report |
    129      * X-Mms-Report-Allowed |
    130      * X-Mms-Sender-Visibility |
    131      * X-Mms-Store |
    132      * X-Mms-Stored |
    133      * X-Mms-Totals |
    134      * X-Mms-Quotas |
    135      * X-Mms-Distribution-Indicator |
    136      * X-Mms-DRM-Content |
    137      * X-Mms-Adaptation-Allowed |
    138      * field types.
    139      */
    140     public static final int VALUE_YES                       = 0x80;
    141     public static final int VALUE_NO                        = 0x81;
    142 
    143     /**
    144      * Delivery-Time |
    145      * Expiry and Reply-Charging-Deadline |
    146      * field type components.
    147      */
    148     public static final int VALUE_ABSOLUTE_TOKEN            = 0x80;
    149     public static final int VALUE_RELATIVE_TOKEN            = 0x81;
    150 
    151     /**
    152      * X-Mms-MMS-Version field types.
    153      */
    154     public static final int MMS_VERSION_1_3                 = ((1 << 4) | 3);
    155     public static final int MMS_VERSION_1_2                 = ((1 << 4) | 2);
    156     public static final int MMS_VERSION_1_1                 = ((1 << 4) | 1);
    157     public static final int MMS_VERSION_1_0                 = ((1 << 4) | 0);
    158 
    159     // Current version is 1.2.
    160     public static final int CURRENT_MMS_VERSION             = MMS_VERSION_1_2;
    161 
    162     /**
    163      * From field type components.
    164      */
    165     public static final int FROM_ADDRESS_PRESENT_TOKEN      = 0x80;
    166     public static final int FROM_INSERT_ADDRESS_TOKEN       = 0x81;
    167 
    168     public static final String FROM_ADDRESS_PRESENT_TOKEN_STR = "address-present-token";
    169 
    170     public static final String FROM_INSERT_ADDRESS_TOKEN_STR = "insert-address-token";
    171 
    172     /**
    173      * X-Mms-Status Field.
    174      */
    175     public static final int STATUS_EXPIRED                  = 0x80;
    176     public static final int STATUS_RETRIEVED                = 0x81;
    177     public static final int STATUS_REJECTED                 = 0x82;
    178     public static final int STATUS_DEFERRED                 = 0x83;
    179     public static final int STATUS_UNRECOGNIZED             = 0x84;
    180     public static final int STATUS_INDETERMINATE            = 0x85;
    181     public static final int STATUS_FORWARDED                = 0x86;
    182     public static final int STATUS_UNREACHABLE              = 0x87;
    183 
    184     /**
    185      * MM-Flags field type components.
    186      */
    187     public static final int MM_FLAGS_ADD_TOKEN              = 0x80;
    188     public static final int MM_FLAGS_REMOVE_TOKEN           = 0x81;
    189     public static final int MM_FLAGS_FILTER_TOKEN           = 0x82;
    190 
    191     /**
    192      * X-Mms-Message-Class field types.
    193      */
    194     public static final int MESSAGE_CLASS_PERSONAL          = 0x80;
    195     public static final int MESSAGE_CLASS_ADVERTISEMENT     = 0x81;
    196     public static final int MESSAGE_CLASS_INFORMATIONAL     = 0x82;
    197     public static final int MESSAGE_CLASS_AUTO              = 0x83;
    198 
    199     public static final String MESSAGE_CLASS_PERSONAL_STR = "personal";
    200 
    201     public static final String MESSAGE_CLASS_ADVERTISEMENT_STR = "advertisement";
    202 
    203     public static final String MESSAGE_CLASS_INFORMATIONAL_STR = "informational";
    204 
    205     public static final String MESSAGE_CLASS_AUTO_STR = "auto";
    206 
    207     /**
    208      * X-Mms-Priority field types.
    209      */
    210     public static final int PRIORITY_LOW                    = 0x80;
    211     public static final int PRIORITY_NORMAL                 = 0x81;
    212     public static final int PRIORITY_HIGH                   = 0x82;
    213 
    214     /**
    215      * X-Mms-Response-Status field types.
    216      */
    217     public static final int RESPONSE_STATUS_OK                   = 0x80;
    218     public static final int RESPONSE_STATUS_ERROR_UNSPECIFIED    = 0x81;
    219     public static final int RESPONSE_STATUS_ERROR_SERVICE_DENIED = 0x82;
    220 
    221     public static final int RESPONSE_STATUS_ERROR_MESSAGE_FORMAT_CORRUPT     = 0x83;
    222     public static final int RESPONSE_STATUS_ERROR_SENDING_ADDRESS_UNRESOLVED = 0x84;
    223 
    224     public static final int RESPONSE_STATUS_ERROR_MESSAGE_NOT_FOUND    = 0x85;
    225     public static final int RESPONSE_STATUS_ERROR_NETWORK_PROBLEM      = 0x86;
    226     public static final int RESPONSE_STATUS_ERROR_CONTENT_NOT_ACCEPTED = 0x87;
    227     public static final int RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE  = 0x88;
    228     public static final int RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE    = 0xC0;
    229 
    230     public static final int RESPONSE_STATUS_ERROR_TRANSIENT_SENDNG_ADDRESS_UNRESOLVED = 0xC1;
    231     public static final int RESPONSE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND         = 0xC2;
    232     public static final int RESPONSE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM           = 0xC3;
    233     public static final int RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS           = 0xC4;
    234 
    235     public static final int RESPONSE_STATUS_ERROR_PERMANENT_FAILURE
    236             = 0xE0;
    237     public static final int RESPONSE_STATUS_ERROR_PERMANENT_SERVICE_DENIED
    238             = 0xE1;
    239     public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT
    240             = 0xE2;
    241     public static final int RESPONSE_STATUS_ERROR_PERMANENT_SENDING_ADDRESS_UNRESOLVED
    242             = 0xE3;
    243     public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND
    244             = 0xE4;
    245     public static final int RESPONSE_STATUS_ERROR_PERMANENT_CONTENT_NOT_ACCEPTED
    246             = 0xE5;
    247     public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_LIMITATIONS_NOT_MET
    248             = 0xE6;
    249     public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_REQUEST_NOT_ACCEPTED
    250             = 0xE7;
    251     public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_FORWARDING_DENIED
    252             = 0xE8;
    253     public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_NOT_SUPPORTED
    254             = 0xE9;
    255     public static final int RESPONSE_STATUS_ERROR_PERMANENT_ADDRESS_HIDING_NOT_SUPPORTED
    256             = 0xEA;
    257     public static final int RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID
    258             = 0xEB;
    259     public static final int RESPONSE_STATUS_ERROR_PERMANENT_END
    260             = 0xFF;
    261 
    262     /**
    263      *  X-Mms-Retrieve-Status field types.
    264      */
    265     public static final int RETRIEVE_STATUS_OK                                  = 0x80;
    266     public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE             = 0xC0;
    267     public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND   = 0xC1;
    268     public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM     = 0xC2;
    269     public static final int RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE             = 0xE0;
    270     public static final int RETRIEVE_STATUS_ERROR_PERMANENT_SERVICE_DENIED      = 0xE1;
    271     public static final int RETRIEVE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND   = 0xE2;
    272     public static final int RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED = 0xE3;
    273     public static final int RETRIEVE_STATUS_ERROR_END                           = 0xFF;
    274 
    275     /**
    276      * X-Mms-Sender-Visibility field types.
    277      */
    278     public static final int SENDER_VISIBILITY_HIDE          = 0x80;
    279     public static final int SENDER_VISIBILITY_SHOW          = 0x81;
    280 
    281     /**
    282      * X-Mms-Read-Status field types.
    283      */
    284     public static final int READ_STATUS_READ                        = 0x80;
    285     public static final int READ_STATUS__DELETED_WITHOUT_BEING_READ = 0x81;
    286 
    287     /**
    288      * X-Mms-Cancel-Status field types.
    289      */
    290     public static final int CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED = 0x80;
    291     public static final int CANCEL_STATUS_REQUEST_CORRUPTED             = 0x81;
    292 
    293     /**
    294      * X-Mms-Reply-Charging field types.
    295      */
    296     public static final int REPLY_CHARGING_REQUESTED           = 0x80;
    297     public static final int REPLY_CHARGING_REQUESTED_TEXT_ONLY = 0x81;
    298     public static final int REPLY_CHARGING_ACCEPTED            = 0x82;
    299     public static final int REPLY_CHARGING_ACCEPTED_TEXT_ONLY  = 0x83;
    300 
    301     /**
    302      * X-Mms-MM-State field types.
    303      */
    304     public static final int MM_STATE_DRAFT                  = 0x80;
    305     public static final int MM_STATE_SENT                   = 0x81;
    306     public static final int MM_STATE_NEW                    = 0x82;
    307     public static final int MM_STATE_RETRIEVED              = 0x83;
    308     public static final int MM_STATE_FORWARDED              = 0x84;
    309 
    310     /**
    311      * X-Mms-Recommended-Retrieval-Mode field types.
    312      */
    313     public static final int RECOMMENDED_RETRIEVAL_MODE_MANUAL = 0x80;
    314 
    315     /**
    316      * X-Mms-Content-Class field types.
    317      */
    318     public static final int CONTENT_CLASS_TEXT              = 0x80;
    319     public static final int CONTENT_CLASS_IMAGE_BASIC       = 0x81;
    320     public static final int CONTENT_CLASS_IMAGE_RICH        = 0x82;
    321     public static final int CONTENT_CLASS_VIDEO_BASIC       = 0x83;
    322     public static final int CONTENT_CLASS_VIDEO_RICH        = 0x84;
    323     public static final int CONTENT_CLASS_MEGAPIXEL         = 0x85;
    324     public static final int CONTENT_CLASS_CONTENT_BASIC     = 0x86;
    325     public static final int CONTENT_CLASS_CONTENT_RICH      = 0x87;
    326 
    327     /**
    328      * X-Mms-Store-Status field types.
    329      */
    330     public static final int STORE_STATUS_SUCCESS                                = 0x80;
    331     public static final int STORE_STATUS_ERROR_TRANSIENT_FAILURE                = 0xC0;
    332     public static final int STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM        = 0xC1;
    333     public static final int STORE_STATUS_ERROR_PERMANENT_FAILURE                = 0xE0;
    334     public static final int STORE_STATUS_ERROR_PERMANENT_SERVICE_DENIED         = 0xE1;
    335     public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT = 0xE2;
    336     public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND      = 0xE3;
    337     public static final int STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL             = 0xE4;
    338     public static final int STORE_STATUS_ERROR_END                              = 0xFF;
    339 
    340     /**
    341      * The map contains the value of all headers.
    342      */
    343     private SparseArray<Object> mHeaderMap = null;
    344 
    345     /**
    346      * Constructor of PduHeaders.
    347      */
    348     public PduHeaders() {
    349         mHeaderMap = new SparseArray<Object>();
    350     }
    351 
    352     /**
    353      * Get octet value by header field.
    354      *
    355      * @param field the field
    356      * @return the octet value of the pdu header
    357      * with specified header field. Return 0 if
    358      * the value is not set.
    359      */
    360     protected int getOctet(int field) {
    361         Integer octet = (Integer) mHeaderMap.get(field);
    362         if (null == octet) {
    363             return 0;
    364         }
    365 
    366         return octet;
    367     }
    368 
    369     /**
    370      * Set octet value to pdu header by header field.
    371      *
    372      * @param value the value
    373      * @param field the field
    374      * @throws InvalidHeaderValueException if the value is invalid.
    375      */
    376     protected void setOctet(int value, int field)
    377             throws InvalidHeaderValueException {
    378         /**
    379          * Check whether this field can be set for specific
    380          * header and check validity of the field.
    381          */
    382         switch (field) {
    383             case REPORT_ALLOWED:
    384             case ADAPTATION_ALLOWED:
    385             case DELIVERY_REPORT:
    386             case DRM_CONTENT:
    387             case DISTRIBUTION_INDICATOR:
    388             case QUOTAS:
    389             case READ_REPORT:
    390             case STORE:
    391             case STORED:
    392             case TOTALS:
    393             case SENDER_VISIBILITY:
    394                 if ((VALUE_YES != value) && (VALUE_NO != value)) {
    395                     // Invalid value.
    396                     throw new InvalidHeaderValueException("Invalid Octet value!");
    397                 }
    398                 break;
    399             case READ_STATUS:
    400                 if ((READ_STATUS_READ != value) &&
    401                         (READ_STATUS__DELETED_WITHOUT_BEING_READ != value)) {
    402                     // Invalid value.
    403                     throw new InvalidHeaderValueException("Invalid Octet value!");
    404                 }
    405                 break;
    406             case CANCEL_STATUS:
    407                 if ((CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED != value) &&
    408                         (CANCEL_STATUS_REQUEST_CORRUPTED != value)) {
    409                     // Invalid value.
    410                     throw new InvalidHeaderValueException("Invalid Octet value!");
    411                 }
    412                 break;
    413             case PRIORITY:
    414                 if ((value < PRIORITY_LOW) || (value > PRIORITY_HIGH)) {
    415                     // Invalid value.
    416                     throw new InvalidHeaderValueException("Invalid Octet value!");
    417                 }
    418                 break;
    419             case STATUS:
    420                 if ((value < STATUS_EXPIRED) || (value > STATUS_UNREACHABLE)) {
    421                     // Invalid value.
    422                     throw new InvalidHeaderValueException("Invalid Octet value!");
    423                 }
    424                 break;
    425             case REPLY_CHARGING:
    426                 if ((value < REPLY_CHARGING_REQUESTED)
    427                         || (value > REPLY_CHARGING_ACCEPTED_TEXT_ONLY)) {
    428                     // Invalid value.
    429                     throw new InvalidHeaderValueException("Invalid Octet value!");
    430                 }
    431                 break;
    432             case MM_STATE:
    433                 if ((value < MM_STATE_DRAFT) || (value > MM_STATE_FORWARDED)) {
    434                     // Invalid value.
    435                     throw new InvalidHeaderValueException("Invalid Octet value!");
    436                 }
    437                 break;
    438             case RECOMMENDED_RETRIEVAL_MODE:
    439                 if (RECOMMENDED_RETRIEVAL_MODE_MANUAL != value) {
    440                     // Invalid value.
    441                     throw new InvalidHeaderValueException("Invalid Octet value!");
    442                 }
    443                 break;
    444             case CONTENT_CLASS:
    445                 if ((value < CONTENT_CLASS_TEXT)
    446                         || (value > CONTENT_CLASS_CONTENT_RICH)) {
    447                     // Invalid value.
    448                     throw new InvalidHeaderValueException("Invalid Octet value!");
    449                 }
    450                 break;
    451             case RETRIEVE_STATUS:
    452                 // According to oma-ts-mms-enc-v1_3, section 7.3.50, we modify the invalid value.
    453                 if ((value > RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
    454                         (value < RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE)) {
    455                     value = RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE;
    456                 } else if ((value > RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED) &&
    457                         (value <= RETRIEVE_STATUS_ERROR_END)) {
    458                     value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
    459                 } else if ((value < RETRIEVE_STATUS_OK) ||
    460                         ((value > RETRIEVE_STATUS_OK) &&
    461                                 (value < RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
    462                         (value > RETRIEVE_STATUS_ERROR_END)) {
    463                     value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
    464                 }
    465                 break;
    466             case STORE_STATUS:
    467                 // According to oma-ts-mms-enc-v1_3, section 7.3.58, we modify the invalid value.
    468                 if ((value > STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
    469                         (value < STORE_STATUS_ERROR_PERMANENT_FAILURE)) {
    470                     value = STORE_STATUS_ERROR_TRANSIENT_FAILURE;
    471                 } else if ((value > STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL) &&
    472                         (value <= STORE_STATUS_ERROR_END)) {
    473                     value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
    474                 } else if ((value < STORE_STATUS_SUCCESS) ||
    475                         ((value > STORE_STATUS_SUCCESS) &&
    476                                 (value < STORE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
    477                         (value > STORE_STATUS_ERROR_END)) {
    478                     value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
    479                 }
    480                 break;
    481             case RESPONSE_STATUS:
    482                 // According to oma-ts-mms-enc-v1_3, section 7.3.48, we modify the invalid value.
    483                 if ((value > RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS) &&
    484                         (value < RESPONSE_STATUS_ERROR_PERMANENT_FAILURE)) {
    485                     value = RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE;
    486                 } else if (((value > RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID) &&
    487                         (value <= RESPONSE_STATUS_ERROR_PERMANENT_END)) ||
    488                         (value < RESPONSE_STATUS_OK) ||
    489                         ((value > RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE) &&
    490                                 (value < RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
    491                         (value > RESPONSE_STATUS_ERROR_PERMANENT_END)) {
    492                     value = RESPONSE_STATUS_ERROR_PERMANENT_FAILURE;
    493                 }
    494                 break;
    495             case MMS_VERSION:
    496                 if ((value < MMS_VERSION_1_0) || (value > MMS_VERSION_1_3)) {
    497                     value = CURRENT_MMS_VERSION; // Current version is the default value.
    498                 }
    499                 break;
    500             case MESSAGE_TYPE:
    501                 if ((value < MESSAGE_TYPE_SEND_REQ) || (value > MESSAGE_TYPE_CANCEL_CONF)) {
    502                     // Invalid value.
    503                     throw new InvalidHeaderValueException("Invalid Octet value!");
    504                 }
    505                 break;
    506             default:
    507                 // This header value should not be Octect.
    508                 throw new RuntimeException("Invalid header field!");
    509         }
    510         mHeaderMap.put(field, value);
    511     }
    512 
    513     /**
    514      * Get TextString value by header field.
    515      *
    516      * @param field the field
    517      * @return the TextString value of the pdu header
    518      * with specified header field
    519      */
    520     protected byte[] getTextString(int field) {
    521         return (byte[]) mHeaderMap.get(field);
    522     }
    523 
    524     /**
    525      * Set TextString value to pdu header by header field.
    526      *
    527      * @param value the value
    528      * @param field the field
    529      * @return the TextString value of the pdu header
    530      * with specified header field
    531      * @throws NullPointerException if the value is null.
    532      */
    533     protected void setTextString(byte[] value, int field) {
    534         /**
    535          * Check whether this field can be set for specific
    536          * header and check validity of the field.
    537          */
    538         if (null == value) {
    539             throw new NullPointerException();
    540         }
    541 
    542         switch (field) {
    543             case TRANSACTION_ID:
    544             case REPLY_CHARGING_ID:
    545             case AUX_APPLIC_ID:
    546             case APPLIC_ID:
    547             case REPLY_APPLIC_ID:
    548             case MESSAGE_ID:
    549             case REPLACE_ID:
    550             case CANCEL_ID:
    551             case CONTENT_LOCATION:
    552             case MESSAGE_CLASS:
    553             case CONTENT_TYPE:
    554                 break;
    555             default:
    556                 // This header value should not be Text-String.
    557                 throw new RuntimeException("Invalid header field!");
    558         }
    559         mHeaderMap.put(field, value);
    560     }
    561 
    562     /**
    563      * Get EncodedStringValue value by header field.
    564      *
    565      * @param field the field
    566      * @return the EncodedStringValue value of the pdu header
    567      * with specified header field
    568      */
    569     protected EncodedStringValue getEncodedStringValue(int field) {
    570         return (EncodedStringValue) mHeaderMap.get(field);
    571     }
    572 
    573     /**
    574      * Get TO, CC or BCC header value.
    575      *
    576      * @param field the field
    577      * @return the EncodeStringValue array of the pdu header
    578      * with specified header field
    579      */
    580     protected EncodedStringValue[] getEncodedStringValues(int field) {
    581         ArrayList<EncodedStringValue> list =
    582                 (ArrayList<EncodedStringValue>) mHeaderMap.get(field);
    583         if (null == list) {
    584             return null;
    585         }
    586         EncodedStringValue[] values = new EncodedStringValue[list.size()];
    587         return list.toArray(values);
    588     }
    589 
    590     /**
    591      * Set EncodedStringValue value to pdu header by header field.
    592      *
    593      * @param value the value
    594      * @param field the field
    595      * @return the EncodedStringValue value of the pdu header
    596      * with specified header field
    597      * @throws NullPointerException if the value is null.
    598      */
    599     protected void setEncodedStringValue(EncodedStringValue value, int field) {
    600         /**
    601          * Check whether this field can be set for specific
    602          * header and check validity of the field.
    603          */
    604         if (null == value) {
    605             throw new NullPointerException();
    606         }
    607 
    608         switch (field) {
    609             case SUBJECT:
    610             case RECOMMENDED_RETRIEVAL_MODE_TEXT:
    611             case RETRIEVE_TEXT:
    612             case STATUS_TEXT:
    613             case STORE_STATUS_TEXT:
    614             case RESPONSE_TEXT:
    615             case FROM:
    616             case PREVIOUSLY_SENT_BY:
    617             case MM_FLAGS:
    618                 break;
    619             default:
    620                 // This header value should not be Encoded-String-Value.
    621                 throw new RuntimeException("Invalid header field!");
    622         }
    623 
    624         mHeaderMap.put(field, value);
    625     }
    626 
    627     /**
    628      * Set TO, CC or BCC header value.
    629      *
    630      * @param value the value
    631      * @param field the field
    632      * @return the EncodedStringValue value array of the pdu header
    633      * with specified header field
    634      * @throws NullPointerException if the value is null.
    635      */
    636     protected void setEncodedStringValues(EncodedStringValue[] value, int field) {
    637         /**
    638          * Check whether this field can be set for specific
    639          * header and check validity of the field.
    640          */
    641         if (null == value) {
    642             throw new NullPointerException();
    643         }
    644 
    645         switch (field) {
    646             case BCC:
    647             case CC:
    648             case TO:
    649                 break;
    650             default:
    651                 // This header value should not be Encoded-String-Value.
    652                 throw new RuntimeException("Invalid header field!");
    653         }
    654 
    655         ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
    656         for (int i = 0; i < value.length; i++) {
    657             list.add(value[i]);
    658         }
    659         mHeaderMap.put(field, list);
    660     }
    661 
    662     /**
    663      * Append one EncodedStringValue to another.
    664      *
    665      * @param value the EncodedStringValue to append
    666      * @param field the field
    667      * @throws NullPointerException if the value is null.
    668      */
    669     protected void appendEncodedStringValue(EncodedStringValue value,
    670             int field) {
    671         if (null == value) {
    672             throw new NullPointerException();
    673         }
    674 
    675         switch (field) {
    676             case BCC:
    677             case CC:
    678             case TO:
    679                 break;
    680             default:
    681                 throw new RuntimeException("Invalid header field!");
    682         }
    683 
    684         ArrayList<EncodedStringValue> list =
    685                 (ArrayList<EncodedStringValue>) mHeaderMap.get(field);
    686         if (null == list) {
    687             list = new ArrayList<EncodedStringValue>();
    688         }
    689         list.add(value);
    690         mHeaderMap.put(field, list);
    691     }
    692 
    693     /**
    694      * Get LongInteger value by header field.
    695      *
    696      * @param field the field
    697      * @return the LongInteger value of the pdu header
    698      * with specified header field. if return -1, the
    699      * field is not existed in pdu header.
    700      */
    701     protected long getLongInteger(int field) {
    702         Long longInteger = (Long) mHeaderMap.get(field);
    703         if (null == longInteger) {
    704             return -1;
    705         }
    706 
    707         return longInteger.longValue();
    708     }
    709 
    710     /**
    711      * Set LongInteger value to pdu header by header field.
    712      *
    713      * @param value the value
    714      * @param field the field
    715      */
    716     protected void setLongInteger(long value, int field) {
    717         /**
    718          * Check whether this field can be set for specific
    719          * header and check validity of the field.
    720          */
    721         switch (field) {
    722             case DATE:
    723             case REPLY_CHARGING_SIZE:
    724             case MESSAGE_SIZE:
    725             case MESSAGE_COUNT:
    726             case START:
    727             case LIMIT:
    728             case DELIVERY_TIME:
    729             case EXPIRY:
    730             case REPLY_CHARGING_DEADLINE:
    731             case PREVIOUSLY_SENT_DATE:
    732                 break;
    733             default:
    734                 // This header value should not be LongInteger.
    735                 throw new RuntimeException("Invalid header field!");
    736         }
    737         mHeaderMap.put(field, value);
    738     }
    739 
    740     public boolean hasHeader(int field) {
    741         return mHeaderMap.get(field, null) != null;
    742     }
    743 }
    744