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