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