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