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