1d02a064168ae5c916b977182b764580e601cb084Wink Saville/*
2d02a064168ae5c916b977182b764580e601cb084Wink Saville * Copyright (C) 2007-2008 Esmertec AG.
3d02a064168ae5c916b977182b764580e601cb084Wink Saville * Copyright (C) 2007-2008 The Android Open Source Project
4d02a064168ae5c916b977182b764580e601cb084Wink Saville *
5d02a064168ae5c916b977182b764580e601cb084Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
6d02a064168ae5c916b977182b764580e601cb084Wink Saville * you may not use this file except in compliance with the License.
7d02a064168ae5c916b977182b764580e601cb084Wink Saville * You may obtain a copy of the License at
8d02a064168ae5c916b977182b764580e601cb084Wink Saville *
9d02a064168ae5c916b977182b764580e601cb084Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
10d02a064168ae5c916b977182b764580e601cb084Wink Saville *
11d02a064168ae5c916b977182b764580e601cb084Wink Saville * Unless required by applicable law or agreed to in writing, software
12d02a064168ae5c916b977182b764580e601cb084Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
13d02a064168ae5c916b977182b764580e601cb084Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14d02a064168ae5c916b977182b764580e601cb084Wink Saville * See the License for the specific language governing permissions and
15d02a064168ae5c916b977182b764580e601cb084Wink Saville * limitations under the License.
16d02a064168ae5c916b977182b764580e601cb084Wink Saville */
17d02a064168ae5c916b977182b764580e601cb084Wink Saville
18d02a064168ae5c916b977182b764580e601cb084Wink Savillepackage com.google.android.mms.pdu;
19d02a064168ae5c916b977182b764580e601cb084Wink Saville
20d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport com.google.android.mms.ContentType;
21d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport com.google.android.mms.InvalidHeaderValueException;
22d02b0b273f4915d1873bbb5472492380451b84ffTom Taylorimport com.google.android.mms.pdu.EncodedStringValue;
23d02a064168ae5c916b977182b764580e601cb084Wink Saville
24d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport android.util.Log;
25d02a064168ae5c916b977182b764580e601cb084Wink Saville
26d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.io.ByteArrayInputStream;
27d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.io.ByteArrayOutputStream;
28d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.io.UnsupportedEncodingException;
29d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.util.Arrays;
30d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.util.HashMap;
31d02a064168ae5c916b977182b764580e601cb084Wink Saville
32d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport android.content.res.Resources;
33d02a064168ae5c916b977182b764580e601cb084Wink Saville
34d02a064168ae5c916b977182b764580e601cb084Wink Savillepublic class PduParser {
35d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
36d02a064168ae5c916b977182b764580e601cb084Wink Saville     *  The next are WAP values defined in WSP specification.
37d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
38d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int QUOTE = 127;
39d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int LENGTH_QUOTE = 31;
40d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int TEXT_MIN = 32;
41d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int TEXT_MAX = 127;
42d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int SHORT_INTEGER_MAX = 127;
43d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int SHORT_LENGTH_MAX = 30;
44d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int LONG_INTEGER_LENGTH_MAX = 8;
45d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int QUOTED_STRING_FLAG = 34;
46d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int END_STRING_FLAG = 0x00;
47d02a064168ae5c916b977182b764580e601cb084Wink Saville    //The next two are used by the interface "parseWapString" to
48d02a064168ae5c916b977182b764580e601cb084Wink Saville    //distinguish Text-String and Quoted-String.
49d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int TYPE_TEXT_STRING = 0;
50d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int TYPE_QUOTED_STRING = 1;
51d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int TYPE_TOKEN_STRING = 2;
52d02a064168ae5c916b977182b764580e601cb084Wink Saville
53d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
54d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Specify the part position.
55d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
56d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int THE_FIRST_PART = 0;
57d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final int THE_LAST_PART = 1;
58d02a064168ae5c916b977182b764580e601cb084Wink Saville
59d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
60d02a064168ae5c916b977182b764580e601cb084Wink Saville     * The pdu data.
61d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
62d02a064168ae5c916b977182b764580e601cb084Wink Saville    private ByteArrayInputStream mPduDataStream = null;
63d02a064168ae5c916b977182b764580e601cb084Wink Saville
64d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
65d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Store pdu headers
66d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
67d02a064168ae5c916b977182b764580e601cb084Wink Saville    private PduHeaders mHeaders = null;
68d02a064168ae5c916b977182b764580e601cb084Wink Saville
69d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
70d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Store pdu parts.
71d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
72d02a064168ae5c916b977182b764580e601cb084Wink Saville    private PduBody mBody = null;
73d02a064168ae5c916b977182b764580e601cb084Wink Saville
74d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
75d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Store the "type" parameter in "Content-Type" header field.
76d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
77d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static byte[] mTypeParam = null;
78d02a064168ae5c916b977182b764580e601cb084Wink Saville
79d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
80d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Store the "start" parameter in "Content-Type" header field.
81d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
82d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static byte[] mStartParam = null;
83d02a064168ae5c916b977182b764580e601cb084Wink Saville
84d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
85d02a064168ae5c916b977182b764580e601cb084Wink Saville     * The log tag.
86d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
87d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final String LOG_TAG = "PduParser";
88d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final boolean DEBUG = false;
89d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static final boolean LOCAL_LOGV = false;
90d02a064168ae5c916b977182b764580e601cb084Wink Saville
91d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
92d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Constructor.
93d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
94d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data to be parsed
95d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
96d02a064168ae5c916b977182b764580e601cb084Wink Saville    public PduParser(byte[] pduDataStream) {
97d02a064168ae5c916b977182b764580e601cb084Wink Saville        mPduDataStream = new ByteArrayInputStream(pduDataStream);
98d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
99d02a064168ae5c916b977182b764580e601cb084Wink Saville
100d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
101d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse the pdu.
102d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
103d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return the pdu structure if parsing successfully.
104d02a064168ae5c916b977182b764580e601cb084Wink Saville     *         null if parsing error happened or mandatory fields are not set.
105d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
106d02a064168ae5c916b977182b764580e601cb084Wink Saville    public GenericPdu parse(){
107d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (mPduDataStream == null) {
108d02a064168ae5c916b977182b764580e601cb084Wink Saville            return null;
109d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
110d02a064168ae5c916b977182b764580e601cb084Wink Saville
111d02a064168ae5c916b977182b764580e601cb084Wink Saville        /* parse headers */
112d02a064168ae5c916b977182b764580e601cb084Wink Saville        mHeaders = parseHeaders(mPduDataStream);
113d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (null == mHeaders) {
114d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Parse headers failed.
115d02a064168ae5c916b977182b764580e601cb084Wink Saville            return null;
116d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
117d02a064168ae5c916b977182b764580e601cb084Wink Saville
118d02a064168ae5c916b977182b764580e601cb084Wink Saville        /* get the message type */
119d02a064168ae5c916b977182b764580e601cb084Wink Saville        int messageType = mHeaders.getOctet(PduHeaders.MESSAGE_TYPE);
120d02a064168ae5c916b977182b764580e601cb084Wink Saville
121d02a064168ae5c916b977182b764580e601cb084Wink Saville        /* check mandatory header fields */
122d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (false == checkMandatoryHeader(mHeaders)) {
123d02a064168ae5c916b977182b764580e601cb084Wink Saville            log("check mandatory headers failed!");
124d02a064168ae5c916b977182b764580e601cb084Wink Saville            return null;
125d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
126d02a064168ae5c916b977182b764580e601cb084Wink Saville
127d02a064168ae5c916b977182b764580e601cb084Wink Saville        if ((PduHeaders.MESSAGE_TYPE_SEND_REQ == messageType) ||
128d02a064168ae5c916b977182b764580e601cb084Wink Saville                (PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF == messageType)) {
129d02a064168ae5c916b977182b764580e601cb084Wink Saville            /* need to parse the parts */
130d02a064168ae5c916b977182b764580e601cb084Wink Saville            mBody = parseParts(mPduDataStream);
131d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (null == mBody) {
132d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Parse parts failed.
133d02a064168ae5c916b977182b764580e601cb084Wink Saville                return null;
134d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
135d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
136d02a064168ae5c916b977182b764580e601cb084Wink Saville
137d02a064168ae5c916b977182b764580e601cb084Wink Saville        switch (messageType) {
138d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
139d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                if (LOCAL_LOGV) {
140d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_SEND_REQ");
141d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                }
142d02a064168ae5c916b977182b764580e601cb084Wink Saville                SendReq sendReq = new SendReq(mHeaders, mBody);
143d02a064168ae5c916b977182b764580e601cb084Wink Saville                return sendReq;
144d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_SEND_CONF:
145d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                if (LOCAL_LOGV) {
146d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_SEND_CONF");
147d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                }
148d02a064168ae5c916b977182b764580e601cb084Wink Saville                SendConf sendConf = new SendConf(mHeaders);
149d02a064168ae5c916b977182b764580e601cb084Wink Saville                return sendConf;
150d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
151d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                if (LOCAL_LOGV) {
152d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_NOTIFICATION_IND");
153d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                }
154d02a064168ae5c916b977182b764580e601cb084Wink Saville                NotificationInd notificationInd =
155d02a064168ae5c916b977182b764580e601cb084Wink Saville                    new NotificationInd(mHeaders);
156d02a064168ae5c916b977182b764580e601cb084Wink Saville                return notificationInd;
157d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
158d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                if (LOCAL_LOGV) {
159d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_NOTIFYRESP_IND");
160d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                }
161d02a064168ae5c916b977182b764580e601cb084Wink Saville                NotifyRespInd notifyRespInd =
162d02a064168ae5c916b977182b764580e601cb084Wink Saville                    new NotifyRespInd(mHeaders);
163d02a064168ae5c916b977182b764580e601cb084Wink Saville                return notifyRespInd;
164d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
165d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                if (LOCAL_LOGV) {
166d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_RETRIEVE_CONF");
167d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                }
168d02a064168ae5c916b977182b764580e601cb084Wink Saville                RetrieveConf retrieveConf =
169d02a064168ae5c916b977182b764580e601cb084Wink Saville                    new RetrieveConf(mHeaders, mBody);
170d02a064168ae5c916b977182b764580e601cb084Wink Saville
171d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] contentType = retrieveConf.getContentType();
172d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == contentType) {
173d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return null;
174d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
175d02a064168ae5c916b977182b764580e601cb084Wink Saville                String ctTypeStr = new String(contentType);
176d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (ctTypeStr.equals(ContentType.MULTIPART_MIXED)
177d02a064168ae5c916b977182b764580e601cb084Wink Saville                        || ctTypeStr.equals(ContentType.MULTIPART_RELATED)
178d02a064168ae5c916b977182b764580e601cb084Wink Saville                        || ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
179d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // The MMS content type must be "application/vnd.wap.multipart.mixed"
180d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // or "application/vnd.wap.multipart.related"
181d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // or "application/vnd.wap.multipart.alternative"
182d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return retrieveConf;
183d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else if (ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
184d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // "application/vnd.wap.multipart.alternative"
185d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // should take only the first part.
186d02a064168ae5c916b977182b764580e601cb084Wink Saville                    PduPart firstPart = mBody.getPart(0);
187d02a064168ae5c916b977182b764580e601cb084Wink Saville                    mBody.removeAll();
188d02a064168ae5c916b977182b764580e601cb084Wink Saville                    mBody.addPart(0, firstPart);
189d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return retrieveConf;
190d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
191d02a064168ae5c916b977182b764580e601cb084Wink Saville                return null;
192d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
193d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                if (LOCAL_LOGV) {
194d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_DELIVERY_IND");
195d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                }
196d02a064168ae5c916b977182b764580e601cb084Wink Saville                DeliveryInd deliveryInd =
197d02a064168ae5c916b977182b764580e601cb084Wink Saville                    new DeliveryInd(mHeaders);
198d02a064168ae5c916b977182b764580e601cb084Wink Saville                return deliveryInd;
199d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
200d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                if (LOCAL_LOGV) {
201d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_ACKNOWLEDGE_IND");
202d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                }
203d02a064168ae5c916b977182b764580e601cb084Wink Saville                AcknowledgeInd acknowledgeInd =
204d02a064168ae5c916b977182b764580e601cb084Wink Saville                    new AcknowledgeInd(mHeaders);
205d02a064168ae5c916b977182b764580e601cb084Wink Saville                return acknowledgeInd;
206d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
207d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                if (LOCAL_LOGV) {
208d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_READ_ORIG_IND");
209d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                }
210d02a064168ae5c916b977182b764580e601cb084Wink Saville                ReadOrigInd readOrigInd =
211d02a064168ae5c916b977182b764580e601cb084Wink Saville                    new ReadOrigInd(mHeaders);
212d02a064168ae5c916b977182b764580e601cb084Wink Saville                return readOrigInd;
213d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
214d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                if (LOCAL_LOGV) {
215d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_READ_REC_IND");
216d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                }
217d02a064168ae5c916b977182b764580e601cb084Wink Saville                ReadRecInd readRecInd =
218d02a064168ae5c916b977182b764580e601cb084Wink Saville                    new ReadRecInd(mHeaders);
219d02a064168ae5c916b977182b764580e601cb084Wink Saville                return readRecInd;
220d02a064168ae5c916b977182b764580e601cb084Wink Saville            default:
221d02a064168ae5c916b977182b764580e601cb084Wink Saville                log("Parser doesn't support this message type in this version!");
222d02a064168ae5c916b977182b764580e601cb084Wink Saville            return null;
223d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
224d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
225d02a064168ae5c916b977182b764580e601cb084Wink Saville
226d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
227d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse pdu headers.
228d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
229d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
230d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return headers in PduHeaders structure, null when parse fail
231d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
232d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected PduHeaders parseHeaders(ByteArrayInputStream pduDataStream){
233d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (pduDataStream == null) {
234d02a064168ae5c916b977182b764580e601cb084Wink Saville            return null;
235d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
236d02a064168ae5c916b977182b764580e601cb084Wink Saville        boolean keepParsing = true;
237d02a064168ae5c916b977182b764580e601cb084Wink Saville        PduHeaders headers = new PduHeaders();
238d02a064168ae5c916b977182b764580e601cb084Wink Saville
239d02a064168ae5c916b977182b764580e601cb084Wink Saville        while (keepParsing && (pduDataStream.available() > 0)) {
240d02a064168ae5c916b977182b764580e601cb084Wink Saville            pduDataStream.mark(1);
241d02a064168ae5c916b977182b764580e601cb084Wink Saville            int headerField = extractByteValue(pduDataStream);
242d02a064168ae5c916b977182b764580e601cb084Wink Saville            /* parse custom text header */
243d02a064168ae5c916b977182b764580e601cb084Wink Saville            if ((headerField >= TEXT_MIN) && (headerField <= TEXT_MAX)) {
244d02a064168ae5c916b977182b764580e601cb084Wink Saville                pduDataStream.reset();
245d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte [] bVal = parseWapString(pduDataStream, TYPE_TEXT_STRING);
246d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (LOCAL_LOGV) {
247d02a064168ae5c916b977182b764580e601cb084Wink Saville                    Log.v(LOG_TAG, "TextHeader: " + new String(bVal));
248d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
249d02a064168ae5c916b977182b764580e601cb084Wink Saville                /* we should ignore it at the moment */
250d02a064168ae5c916b977182b764580e601cb084Wink Saville                continue;
251d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
252d02a064168ae5c916b977182b764580e601cb084Wink Saville            switch (headerField) {
253d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.MESSAGE_TYPE:
254d02a064168ae5c916b977182b764580e601cb084Wink Saville                {
255d02a064168ae5c916b977182b764580e601cb084Wink Saville                    int messageType = extractByteValue(pduDataStream);
256d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    if (LOCAL_LOGV) {
257d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        Log.v(LOG_TAG, "parseHeaders: messageType: " + messageType);
258d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    }
259d02a064168ae5c916b977182b764580e601cb084Wink Saville                    switch (messageType) {
260d02a064168ae5c916b977182b764580e601cb084Wink Saville                        // We don't support these kind of messages now.
261d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_FORWARD_REQ:
262d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_FORWARD_CONF:
263d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ:
264d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF:
265d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ:
266d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF:
267d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ:
268d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF:
269d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ:
270d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF:
271d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_MBOX_DESCR:
272d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_DELETE_REQ:
273d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_DELETE_CONF:
274d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_CANCEL_REQ:
275d02a064168ae5c916b977182b764580e601cb084Wink Saville                        case PduHeaders.MESSAGE_TYPE_CANCEL_CONF:
276d02a064168ae5c916b977182b764580e601cb084Wink Saville                            return null;
277d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
278d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
279d02a064168ae5c916b977182b764580e601cb084Wink Saville                        headers.setOctet(messageType, headerField);
280d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(InvalidHeaderValueException e) {
281d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log("Set invalid Octet value: " + messageType +
282d02a064168ae5c916b977182b764580e601cb084Wink Saville                                " into the header filed: " + headerField);
283d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
284d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
285d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + "is not Octet header field!");
286d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
287d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
288d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
289d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
290d02a064168ae5c916b977182b764580e601cb084Wink Saville                /* Octect value */
291d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.REPORT_ALLOWED:
292d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.ADAPTATION_ALLOWED:
293d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.DELIVERY_REPORT:
294d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.DRM_CONTENT:
295d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.DISTRIBUTION_INDICATOR:
296d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.QUOTAS:
297d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.READ_REPORT:
298d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.STORE:
299d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.STORED:
300d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.TOTALS:
301d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.SENDER_VISIBILITY:
302d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.READ_STATUS:
303d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.CANCEL_STATUS:
304d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.PRIORITY:
305d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.STATUS:
306d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.REPLY_CHARGING:
307d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.MM_STATE:
308d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.RECOMMENDED_RETRIEVAL_MODE:
309d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.CONTENT_CLASS:
310d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.RETRIEVE_STATUS:
311d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.STORE_STATUS:
312d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /**
313d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * The following field has a different value when
314d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * used in the M-Mbox-Delete.conf and M-Delete.conf PDU.
315d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * For now we ignore this fact, since we do not support these PDUs
316d02a064168ae5c916b977182b764580e601cb084Wink Saville                     */
317d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.RESPONSE_STATUS:
318d02a064168ae5c916b977182b764580e601cb084Wink Saville                {
319d02a064168ae5c916b977182b764580e601cb084Wink Saville                    int value = extractByteValue(pduDataStream);
320d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    if (LOCAL_LOGV) {
321d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        Log.v(LOG_TAG, "parseHeaders: byte: " + headerField + " value: " +
322d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                value);
323d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    }
324d02a064168ae5c916b977182b764580e601cb084Wink Saville
325d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
326d02a064168ae5c916b977182b764580e601cb084Wink Saville                        headers.setOctet(value, headerField);
327d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(InvalidHeaderValueException e) {
328d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log("Set invalid Octet value: " + value +
329d02a064168ae5c916b977182b764580e601cb084Wink Saville                                " into the header filed: " + headerField);
330d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
331d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
332d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + "is not Octet header field!");
333d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
334d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
335d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
336d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
337d02a064168ae5c916b977182b764580e601cb084Wink Saville
338d02a064168ae5c916b977182b764580e601cb084Wink Saville                /* Long-Integer */
339d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.DATE:
340d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.REPLY_CHARGING_SIZE:
341d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.MESSAGE_SIZE:
342d02a064168ae5c916b977182b764580e601cb084Wink Saville                {
343d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
344d02a064168ae5c916b977182b764580e601cb084Wink Saville                        long value = parseLongInteger(pduDataStream);
345d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        if (LOCAL_LOGV) {
346d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            Log.v(LOG_TAG, "parseHeaders: longint: " + headerField + " value: " +
347d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                    value);
348d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        }
349d02a064168ae5c916b977182b764580e601cb084Wink Saville                        headers.setLongInteger(value, headerField);
350d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
351d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + "is not Long-Integer header field!");
352d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
353d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
354d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
355d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
356d02a064168ae5c916b977182b764580e601cb084Wink Saville
357d02a064168ae5c916b977182b764580e601cb084Wink Saville                /* Integer-Value */
358d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.MESSAGE_COUNT:
359d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.START:
360d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.LIMIT:
361d02a064168ae5c916b977182b764580e601cb084Wink Saville                {
362d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
363d02a064168ae5c916b977182b764580e601cb084Wink Saville                        long value = parseIntegerValue(pduDataStream);
364d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        if (LOCAL_LOGV) {
365d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            Log.v(LOG_TAG, "parseHeaders: int: " + headerField + " value: " +
366d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                    value);
367d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        }
368d02a064168ae5c916b977182b764580e601cb084Wink Saville                        headers.setLongInteger(value, headerField);
369d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
370d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + "is not Long-Integer header field!");
371d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
372d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
373d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
374d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
375d02a064168ae5c916b977182b764580e601cb084Wink Saville
376d02a064168ae5c916b977182b764580e601cb084Wink Saville                /* Text-String */
377d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.TRANSACTION_ID:
378d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.REPLY_CHARGING_ID:
379d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.AUX_APPLIC_ID:
380d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.APPLIC_ID:
381d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.REPLY_APPLIC_ID:
382d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /**
383d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * The next three header fields are email addresses
384d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * as defined in RFC2822,
385d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * not including the characters "<" and ">"
386d02a064168ae5c916b977182b764580e601cb084Wink Saville                     */
387d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.MESSAGE_ID:
388d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.REPLACE_ID:
389d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.CANCEL_ID:
390d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /**
391d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * The following field has a different value when
392d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * used in the M-Mbox-Delete.conf and M-Delete.conf PDU.
393d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * For now we ignore this fact, since we do not support these PDUs
394d02a064168ae5c916b977182b764580e601cb084Wink Saville                     */
395d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.CONTENT_LOCATION:
396d02a064168ae5c916b977182b764580e601cb084Wink Saville                {
397d02a064168ae5c916b977182b764580e601cb084Wink Saville                    byte[] value = parseWapString(pduDataStream, TYPE_TEXT_STRING);
398d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (null != value) {
399d02a064168ae5c916b977182b764580e601cb084Wink Saville                        try {
400d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            if (LOCAL_LOGV) {
401d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                Log.v(LOG_TAG, "parseHeaders: string: " + headerField + " value: " +
402d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                        new String(value));
403d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            }
404d02a064168ae5c916b977182b764580e601cb084Wink Saville                            headers.setTextString(value, headerField);
405d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(NullPointerException e) {
406d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log("null pointer error!");
407d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(RuntimeException e) {
408d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log(headerField + "is not Text-String header field!");
409d02a064168ae5c916b977182b764580e601cb084Wink Saville                            return null;
410d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
411d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
412d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
413d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
414d02a064168ae5c916b977182b764580e601cb084Wink Saville
415d02a064168ae5c916b977182b764580e601cb084Wink Saville                /* Encoded-string-value */
416d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.SUBJECT:
417d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.RECOMMENDED_RETRIEVAL_MODE_TEXT:
418d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.RETRIEVE_TEXT:
419d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.STATUS_TEXT:
420d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.STORE_STATUS_TEXT:
421d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* the next one is not support
422d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * M-Mbox-Delete.conf and M-Delete.conf now */
423d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.RESPONSE_TEXT:
424d02a064168ae5c916b977182b764580e601cb084Wink Saville                {
425d02a064168ae5c916b977182b764580e601cb084Wink Saville                    EncodedStringValue value =
426d02a064168ae5c916b977182b764580e601cb084Wink Saville                        parseEncodedStringValue(pduDataStream);
427d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (null != value) {
428d02a064168ae5c916b977182b764580e601cb084Wink Saville                        try {
429d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            if (LOCAL_LOGV) {
430d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                Log.v(LOG_TAG, "parseHeaders: encoded string: " + headerField
431d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                        + " value: " + value.getString());
432d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            }
433d02a064168ae5c916b977182b764580e601cb084Wink Saville                            headers.setEncodedStringValue(value, headerField);
434d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(NullPointerException e) {
435d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log("null pointer error!");
436d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch (RuntimeException e) {
437d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log(headerField + "is not Encoded-String-Value header field!");
438d02a064168ae5c916b977182b764580e601cb084Wink Saville                            return null;
439d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
440d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
441d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
442d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
443d02a064168ae5c916b977182b764580e601cb084Wink Saville
444d02a064168ae5c916b977182b764580e601cb084Wink Saville                /* Addressing model */
445d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.BCC:
446d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.CC:
447d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.TO:
448d02a064168ae5c916b977182b764580e601cb084Wink Saville                {
449d02a064168ae5c916b977182b764580e601cb084Wink Saville                    EncodedStringValue value =
450d02a064168ae5c916b977182b764580e601cb084Wink Saville                        parseEncodedStringValue(pduDataStream);
451d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (null != value) {
452d02a064168ae5c916b977182b764580e601cb084Wink Saville                        byte[] address = value.getTextString();
453d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if (null != address) {
454d02a064168ae5c916b977182b764580e601cb084Wink Saville                            String str = new String(address);
455d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            if (LOCAL_LOGV) {
456d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                Log.v(LOG_TAG, "parseHeaders: (to/cc/bcc) address: " + headerField
457d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                        + " value: " + str);
458d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            }
459d02a064168ae5c916b977182b764580e601cb084Wink Saville                            int endIndex = str.indexOf("/");
460d02a064168ae5c916b977182b764580e601cb084Wink Saville                            if (endIndex > 0) {
461d02a064168ae5c916b977182b764580e601cb084Wink Saville                                str = str.substring(0, endIndex);
462d02a064168ae5c916b977182b764580e601cb084Wink Saville                            }
463d02a064168ae5c916b977182b764580e601cb084Wink Saville                            try {
464d02a064168ae5c916b977182b764580e601cb084Wink Saville                                value.setTextString(str.getBytes());
465d02a064168ae5c916b977182b764580e601cb084Wink Saville                            } catch(NullPointerException e) {
466d02a064168ae5c916b977182b764580e601cb084Wink Saville                                log("null pointer error!");
467d02a064168ae5c916b977182b764580e601cb084Wink Saville                                return null;
468d02a064168ae5c916b977182b764580e601cb084Wink Saville                            }
469d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
470d02a064168ae5c916b977182b764580e601cb084Wink Saville
471d02a064168ae5c916b977182b764580e601cb084Wink Saville                        try {
472d02a064168ae5c916b977182b764580e601cb084Wink Saville                            headers.appendEncodedStringValue(value, headerField);
473d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(NullPointerException e) {
474d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log("null pointer error!");
475d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(RuntimeException e) {
476d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log(headerField + "is not Encoded-String-Value header field!");
477d02a064168ae5c916b977182b764580e601cb084Wink Saville                            return null;
478d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
479d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
480d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
481d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
482d02a064168ae5c916b977182b764580e601cb084Wink Saville
483d02a064168ae5c916b977182b764580e601cb084Wink Saville                /* Value-length
484d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * (Absolute-token Date-value | Relative-token Delta-seconds-value) */
485d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.DELIVERY_TIME:
486d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.EXPIRY:
487d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.REPLY_CHARGING_DEADLINE:
488d02a064168ae5c916b977182b764580e601cb084Wink Saville                {
489d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* parse Value-length */
490d02a064168ae5c916b977182b764580e601cb084Wink Saville                    parseValueLength(pduDataStream);
491d02a064168ae5c916b977182b764580e601cb084Wink Saville
492d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Absolute-token or Relative-token */
493d02a064168ae5c916b977182b764580e601cb084Wink Saville                    int token = extractByteValue(pduDataStream);
494d02a064168ae5c916b977182b764580e601cb084Wink Saville
495d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Date-value or Delta-seconds-value */
496d02a064168ae5c916b977182b764580e601cb084Wink Saville                    long timeValue;
497d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
498d02a064168ae5c916b977182b764580e601cb084Wink Saville                        timeValue = parseLongInteger(pduDataStream);
499d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
500d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + "is not Long-Integer header field!");
501d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
502d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
503d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (PduHeaders.VALUE_RELATIVE_TOKEN == token) {
504d02a064168ae5c916b977182b764580e601cb084Wink Saville                        /* need to convert the Delta-seconds-value
505d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * into Date-value */
506d02a064168ae5c916b977182b764580e601cb084Wink Saville                        timeValue = System.currentTimeMillis()/1000 + timeValue;
507d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
508d02a064168ae5c916b977182b764580e601cb084Wink Saville
509d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
510d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        if (LOCAL_LOGV) {
511d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            Log.v(LOG_TAG, "parseHeaders: time value: " + headerField
512d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                    + " value: " + timeValue);
513d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        }
514d02a064168ae5c916b977182b764580e601cb084Wink Saville                        headers.setLongInteger(timeValue, headerField);
515d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
516d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + "is not Long-Integer header field!");
517d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
518d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
519d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
520d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
521d02a064168ae5c916b977182b764580e601cb084Wink Saville
522d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.FROM: {
523d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* From-value =
524d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * Value-length
525d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * (Address-present-token Encoded-string-value | Insert-address-token)
526d02a064168ae5c916b977182b764580e601cb084Wink Saville                     */
527d02a064168ae5c916b977182b764580e601cb084Wink Saville                    EncodedStringValue from = null;
528d02a064168ae5c916b977182b764580e601cb084Wink Saville                    parseValueLength(pduDataStream); /* parse value-length */
529d02a064168ae5c916b977182b764580e601cb084Wink Saville
530d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Address-present-token or Insert-address-token */
531d02a064168ae5c916b977182b764580e601cb084Wink Saville                    int fromToken = extractByteValue(pduDataStream);
532d02a064168ae5c916b977182b764580e601cb084Wink Saville
533d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Address-present-token or Insert-address-token */
534d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (PduHeaders.FROM_ADDRESS_PRESENT_TOKEN == fromToken) {
535d02a064168ae5c916b977182b764580e601cb084Wink Saville                        /* Encoded-string-value */
536d02a064168ae5c916b977182b764580e601cb084Wink Saville                        from = parseEncodedStringValue(pduDataStream);
537d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if (null != from) {
538d02a064168ae5c916b977182b764580e601cb084Wink Saville                            byte[] address = from.getTextString();
539d02a064168ae5c916b977182b764580e601cb084Wink Saville                            if (null != address) {
540d02a064168ae5c916b977182b764580e601cb084Wink Saville                                String str = new String(address);
541d02a064168ae5c916b977182b764580e601cb084Wink Saville                                int endIndex = str.indexOf("/");
542d02a064168ae5c916b977182b764580e601cb084Wink Saville                                if (endIndex > 0) {
543d02a064168ae5c916b977182b764580e601cb084Wink Saville                                    str = str.substring(0, endIndex);
544d02a064168ae5c916b977182b764580e601cb084Wink Saville                                }
545d02a064168ae5c916b977182b764580e601cb084Wink Saville                                try {
546d02a064168ae5c916b977182b764580e601cb084Wink Saville                                    from.setTextString(str.getBytes());
547d02a064168ae5c916b977182b764580e601cb084Wink Saville                                } catch(NullPointerException e) {
548d02a064168ae5c916b977182b764580e601cb084Wink Saville                                    log("null pointer error!");
549d02a064168ae5c916b977182b764580e601cb084Wink Saville                                    return null;
550d02a064168ae5c916b977182b764580e601cb084Wink Saville                                }
551d02a064168ae5c916b977182b764580e601cb084Wink Saville                            }
552d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
553d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } else {
554d02a064168ae5c916b977182b764580e601cb084Wink Saville                        try {
555d02a064168ae5c916b977182b764580e601cb084Wink Saville                            from = new EncodedStringValue(
556d02a064168ae5c916b977182b764580e601cb084Wink Saville                                    PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes());
557d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(NullPointerException e) {
558d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log(headerField + "is not Encoded-String-Value header field!");
559d02a064168ae5c916b977182b764580e601cb084Wink Saville                            return null;
560d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
561d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
562d02a064168ae5c916b977182b764580e601cb084Wink Saville
563d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
564d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        if (LOCAL_LOGV) {
565d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            Log.v(LOG_TAG, "parseHeaders: from address: " + headerField
566d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                    + " value: " + from.getString());
567d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        }
568d02a064168ae5c916b977182b764580e601cb084Wink Saville                        headers.setEncodedStringValue(from, PduHeaders.FROM);
569d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(NullPointerException e) {
570d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log("null pointer error!");
571d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
572d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + "is not Encoded-String-Value header field!");
573d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
574d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
575d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
576d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
577d02a064168ae5c916b977182b764580e601cb084Wink Saville
578d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.MESSAGE_CLASS: {
579d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Message-class-value = Class-identifier | Token-text */
580d02a064168ae5c916b977182b764580e601cb084Wink Saville                    pduDataStream.mark(1);
581d02a064168ae5c916b977182b764580e601cb084Wink Saville                    int messageClass = extractByteValue(pduDataStream);
582d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    if (LOCAL_LOGV) {
583d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        Log.v(LOG_TAG, "parseHeaders: MESSAGE_CLASS: " + headerField
584d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                + " value: " + messageClass);
585d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    }
586d02a064168ae5c916b977182b764580e601cb084Wink Saville
587d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (messageClass >= PduHeaders.MESSAGE_CLASS_PERSONAL) {
588d02a064168ae5c916b977182b764580e601cb084Wink Saville                        /* Class-identifier */
589d02a064168ae5c916b977182b764580e601cb084Wink Saville                        try {
590d02a064168ae5c916b977182b764580e601cb084Wink Saville                            if (PduHeaders.MESSAGE_CLASS_PERSONAL == messageClass) {
591d02a064168ae5c916b977182b764580e601cb084Wink Saville                                headers.setTextString(
592d02a064168ae5c916b977182b764580e601cb084Wink Saville                                        PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes(),
593d02a064168ae5c916b977182b764580e601cb084Wink Saville                                        PduHeaders.MESSAGE_CLASS);
594d02a064168ae5c916b977182b764580e601cb084Wink Saville                            } else if (PduHeaders.MESSAGE_CLASS_ADVERTISEMENT == messageClass) {
595d02a064168ae5c916b977182b764580e601cb084Wink Saville                                headers.setTextString(
596d02a064168ae5c916b977182b764580e601cb084Wink Saville                                        PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes(),
597d02a064168ae5c916b977182b764580e601cb084Wink Saville                                        PduHeaders.MESSAGE_CLASS);
598d02a064168ae5c916b977182b764580e601cb084Wink Saville                            } else if (PduHeaders.MESSAGE_CLASS_INFORMATIONAL == messageClass) {
599d02a064168ae5c916b977182b764580e601cb084Wink Saville                                headers.setTextString(
600d02a064168ae5c916b977182b764580e601cb084Wink Saville                                        PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes(),
601d02a064168ae5c916b977182b764580e601cb084Wink Saville                                        PduHeaders.MESSAGE_CLASS);
602d02a064168ae5c916b977182b764580e601cb084Wink Saville                            } else if (PduHeaders.MESSAGE_CLASS_AUTO == messageClass) {
603d02a064168ae5c916b977182b764580e601cb084Wink Saville                                headers.setTextString(
604d02a064168ae5c916b977182b764580e601cb084Wink Saville                                        PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes(),
605d02a064168ae5c916b977182b764580e601cb084Wink Saville                                        PduHeaders.MESSAGE_CLASS);
606d02a064168ae5c916b977182b764580e601cb084Wink Saville                            }
607d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(NullPointerException e) {
608d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log("null pointer error!");
609d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(RuntimeException e) {
610d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log(headerField + "is not Text-String header field!");
611d02a064168ae5c916b977182b764580e601cb084Wink Saville                            return null;
612d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
613d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } else {
614d02a064168ae5c916b977182b764580e601cb084Wink Saville                        /* Token-text */
615d02a064168ae5c916b977182b764580e601cb084Wink Saville                        pduDataStream.reset();
616d02a064168ae5c916b977182b764580e601cb084Wink Saville                        byte[] messageClassString = parseWapString(pduDataStream, TYPE_TEXT_STRING);
617d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if (null != messageClassString) {
618d02a064168ae5c916b977182b764580e601cb084Wink Saville                            try {
619d02a064168ae5c916b977182b764580e601cb084Wink Saville                                headers.setTextString(messageClassString, PduHeaders.MESSAGE_CLASS);
620d02a064168ae5c916b977182b764580e601cb084Wink Saville                            } catch(NullPointerException e) {
621d02a064168ae5c916b977182b764580e601cb084Wink Saville                                log("null pointer error!");
622d02a064168ae5c916b977182b764580e601cb084Wink Saville                            } catch(RuntimeException e) {
623d02a064168ae5c916b977182b764580e601cb084Wink Saville                                log(headerField + "is not Text-String header field!");
624d02a064168ae5c916b977182b764580e601cb084Wink Saville                                return null;
625d02a064168ae5c916b977182b764580e601cb084Wink Saville                            }
626d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
627d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
628d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
629d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
630d02a064168ae5c916b977182b764580e601cb084Wink Saville
631d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.MMS_VERSION: {
632d02a064168ae5c916b977182b764580e601cb084Wink Saville                    int version = parseShortInteger(pduDataStream);
633d02a064168ae5c916b977182b764580e601cb084Wink Saville
634d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
635d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        if (LOCAL_LOGV) {
636d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            Log.v(LOG_TAG, "parseHeaders: MMS_VERSION: " + headerField
637d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                    + " value: " + version);
638d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        }
639d02a064168ae5c916b977182b764580e601cb084Wink Saville                        headers.setOctet(version, PduHeaders.MMS_VERSION);
640d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(InvalidHeaderValueException e) {
641d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log("Set invalid Octet value: " + version +
642d02a064168ae5c916b977182b764580e601cb084Wink Saville                                " into the header filed: " + headerField);
643d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
644d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
645d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + "is not Octet header field!");
646d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
647d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
648d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
649d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
650d02a064168ae5c916b977182b764580e601cb084Wink Saville
651d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.PREVIOUSLY_SENT_BY: {
652d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Previously-sent-by-value =
653d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * Value-length Forwarded-count-value Encoded-string-value */
654d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* parse value-length */
655d02a064168ae5c916b977182b764580e601cb084Wink Saville                    parseValueLength(pduDataStream);
656d02a064168ae5c916b977182b764580e601cb084Wink Saville
657d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* parse Forwarded-count-value */
658d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
659d02a064168ae5c916b977182b764580e601cb084Wink Saville                        parseIntegerValue(pduDataStream);
660d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
661d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + " is not Integer-Value");
662d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
663d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
664d02a064168ae5c916b977182b764580e601cb084Wink Saville
665d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* parse Encoded-string-value */
666d02a064168ae5c916b977182b764580e601cb084Wink Saville                    EncodedStringValue previouslySentBy =
667d02a064168ae5c916b977182b764580e601cb084Wink Saville                        parseEncodedStringValue(pduDataStream);
668d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (null != previouslySentBy) {
669d02a064168ae5c916b977182b764580e601cb084Wink Saville                        try {
670d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            if (LOCAL_LOGV) {
671d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                Log.v(LOG_TAG, "parseHeaders: PREVIOUSLY_SENT_BY: " + headerField
672d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                        + " value: " + previouslySentBy.getString());
673d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            }
674d02a064168ae5c916b977182b764580e601cb084Wink Saville                            headers.setEncodedStringValue(previouslySentBy,
675d02a064168ae5c916b977182b764580e601cb084Wink Saville                                    PduHeaders.PREVIOUSLY_SENT_BY);
676d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(NullPointerException e) {
677d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log("null pointer error!");
678d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(RuntimeException e) {
679d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log(headerField + "is not Encoded-String-Value header field!");
680d02a064168ae5c916b977182b764580e601cb084Wink Saville                            return null;
681d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
682d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
683d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
684d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
685d02a064168ae5c916b977182b764580e601cb084Wink Saville
686d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.PREVIOUSLY_SENT_DATE: {
687d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Previously-sent-date-value =
688d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * Value-length Forwarded-count-value Date-value */
689d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* parse value-length */
690d02a064168ae5c916b977182b764580e601cb084Wink Saville                    parseValueLength(pduDataStream);
691d02a064168ae5c916b977182b764580e601cb084Wink Saville
692d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* parse Forwarded-count-value */
693d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
694d02a064168ae5c916b977182b764580e601cb084Wink Saville                        parseIntegerValue(pduDataStream);
695d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
696d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + " is not Integer-Value");
697d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
698d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
699d02a064168ae5c916b977182b764580e601cb084Wink Saville
700d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Date-value */
701d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
702d02a064168ae5c916b977182b764580e601cb084Wink Saville                        long perviouslySentDate = parseLongInteger(pduDataStream);
703d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        if (LOCAL_LOGV) {
704d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            Log.v(LOG_TAG, "parseHeaders: PREVIOUSLY_SENT_DATE: " + headerField
705d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                    + " value: " + perviouslySentDate);
706d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        }
707d02a064168ae5c916b977182b764580e601cb084Wink Saville                        headers.setLongInteger(perviouslySentDate,
708d02a064168ae5c916b977182b764580e601cb084Wink Saville                                PduHeaders.PREVIOUSLY_SENT_DATE);
709d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
710d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + "is not Long-Integer header field!");
711d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
712d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
713d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
714d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
715d02a064168ae5c916b977182b764580e601cb084Wink Saville
716d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.MM_FLAGS: {
717d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* MM-flags-value =
718d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * Value-length
719d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * ( Add-token | Remove-token | Filter-token )
720d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * Encoded-string-value
721d02a064168ae5c916b977182b764580e601cb084Wink Saville                     */
722d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    if (LOCAL_LOGV) {
723d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        Log.v(LOG_TAG, "parseHeaders: MM_FLAGS: " + headerField
724d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                + " NOT REALLY SUPPORTED");
725d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    }
726d02a064168ae5c916b977182b764580e601cb084Wink Saville
727d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* parse Value-length */
728d02a064168ae5c916b977182b764580e601cb084Wink Saville                    parseValueLength(pduDataStream);
729d02a064168ae5c916b977182b764580e601cb084Wink Saville
730d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Add-token | Remove-token | Filter-token */
731d02a064168ae5c916b977182b764580e601cb084Wink Saville                    extractByteValue(pduDataStream);
732d02a064168ae5c916b977182b764580e601cb084Wink Saville
733d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Encoded-string-value */
734d02a064168ae5c916b977182b764580e601cb084Wink Saville                    parseEncodedStringValue(pduDataStream);
735d02a064168ae5c916b977182b764580e601cb084Wink Saville
736d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* not store this header filed in "headers",
737d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * because now PduHeaders doesn't support it */
738d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
739d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
740d02a064168ae5c916b977182b764580e601cb084Wink Saville
741d02a064168ae5c916b977182b764580e601cb084Wink Saville                /* Value-length
742d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * (Message-total-token | Size-total-token) Integer-Value */
743d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.MBOX_TOTALS:
744d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.MBOX_QUOTAS:
745d02a064168ae5c916b977182b764580e601cb084Wink Saville                {
746d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    if (LOCAL_LOGV) {
747d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        Log.v(LOG_TAG, "parseHeaders: MBOX_TOTALS: " + headerField);
748d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    }
749d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Value-length */
750d02a064168ae5c916b977182b764580e601cb084Wink Saville                    parseValueLength(pduDataStream);
751d02a064168ae5c916b977182b764580e601cb084Wink Saville
752d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* Message-total-token | Size-total-token */
753d02a064168ae5c916b977182b764580e601cb084Wink Saville                    extractByteValue(pduDataStream);
754d02a064168ae5c916b977182b764580e601cb084Wink Saville
755d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /*Integer-Value*/
756d02a064168ae5c916b977182b764580e601cb084Wink Saville                    try {
757d02a064168ae5c916b977182b764580e601cb084Wink Saville                        parseIntegerValue(pduDataStream);
758d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } catch(RuntimeException e) {
759d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log(headerField + " is not Integer-Value");
760d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
761d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
762d02a064168ae5c916b977182b764580e601cb084Wink Saville
763d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* not store these headers filed in "headers",
764d02a064168ae5c916b977182b764580e601cb084Wink Saville                    because now PduHeaders doesn't support them */
765d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
766d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
767d02a064168ae5c916b977182b764580e601cb084Wink Saville
768d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.ELEMENT_DESCRIPTOR: {
769d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    if (LOCAL_LOGV) {
770d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        Log.v(LOG_TAG, "parseHeaders: ELEMENT_DESCRIPTOR: " + headerField);
771d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    }
772d02a064168ae5c916b977182b764580e601cb084Wink Saville                    parseContentType(pduDataStream, null);
773d02a064168ae5c916b977182b764580e601cb084Wink Saville
774d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* not store this header filed in "headers",
775d02a064168ae5c916b977182b764580e601cb084Wink Saville                    because now PduHeaders doesn't support it */
776d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
777d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
778d02a064168ae5c916b977182b764580e601cb084Wink Saville
779d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.CONTENT_TYPE: {
780d02a064168ae5c916b977182b764580e601cb084Wink Saville                    HashMap<Integer, Object> map =
781d02a064168ae5c916b977182b764580e601cb084Wink Saville                        new HashMap<Integer, Object>();
782d02a064168ae5c916b977182b764580e601cb084Wink Saville                    byte[] contentType =
783d02a064168ae5c916b977182b764580e601cb084Wink Saville                        parseContentType(pduDataStream, map);
784d02a064168ae5c916b977182b764580e601cb084Wink Saville
785d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (null != contentType) {
786d02a064168ae5c916b977182b764580e601cb084Wink Saville                        try {
787d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            if (LOCAL_LOGV) {
788d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                Log.v(LOG_TAG, "parseHeaders: CONTENT_TYPE: " + headerField +
789d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                                        contentType.toString());
790d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                            }
791d02a064168ae5c916b977182b764580e601cb084Wink Saville                            headers.setTextString(contentType, PduHeaders.CONTENT_TYPE);
792d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(NullPointerException e) {
793d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log("null pointer error!");
794d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch(RuntimeException e) {
795d02a064168ae5c916b977182b764580e601cb084Wink Saville                            log(headerField + "is not Text-String header field!");
796d02a064168ae5c916b977182b764580e601cb084Wink Saville                            return null;
797d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
798d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
799d02a064168ae5c916b977182b764580e601cb084Wink Saville
800d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* get start parameter */
801d02a064168ae5c916b977182b764580e601cb084Wink Saville                    mStartParam = (byte[]) map.get(PduPart.P_START);
802d02a064168ae5c916b977182b764580e601cb084Wink Saville
803d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /* get charset parameter */
804d02a064168ae5c916b977182b764580e601cb084Wink Saville                    mTypeParam= (byte[]) map.get(PduPart.P_TYPE);
805d02a064168ae5c916b977182b764580e601cb084Wink Saville
806d02a064168ae5c916b977182b764580e601cb084Wink Saville                    keepParsing = false;
807d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
808d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
809d02a064168ae5c916b977182b764580e601cb084Wink Saville
810d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.CONTENT:
811d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.ADDITIONAL_HEADERS:
812d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduHeaders.ATTRIBUTES:
813d02a064168ae5c916b977182b764580e601cb084Wink Saville                default: {
814d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    if (LOCAL_LOGV) {
815d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                        Log.v(LOG_TAG, "parseHeaders: Unknown header: " + headerField);
816d02b0b273f4915d1873bbb5472492380451b84ffTom Taylor                    }
817d02a064168ae5c916b977182b764580e601cb084Wink Saville                    log("Unknown header");
818d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
819d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
820d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
821d02a064168ae5c916b977182b764580e601cb084Wink Saville
822d02a064168ae5c916b977182b764580e601cb084Wink Saville        return headers;
823d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
824d02a064168ae5c916b977182b764580e601cb084Wink Saville
825d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
826d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse pdu parts.
827d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
828d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
829d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return parts in PduBody structure
830d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
831d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static PduBody parseParts(ByteArrayInputStream pduDataStream) {
832d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (pduDataStream == null) {
833d02a064168ae5c916b977182b764580e601cb084Wink Saville            return null;
834d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
835d02a064168ae5c916b977182b764580e601cb084Wink Saville
836d02a064168ae5c916b977182b764580e601cb084Wink Saville        int count = parseUnsignedInt(pduDataStream); // get the number of parts
837d02a064168ae5c916b977182b764580e601cb084Wink Saville        PduBody body = new PduBody();
838d02a064168ae5c916b977182b764580e601cb084Wink Saville
839d02a064168ae5c916b977182b764580e601cb084Wink Saville        for (int i = 0 ; i < count ; i++) {
840d02a064168ae5c916b977182b764580e601cb084Wink Saville            int headerLength = parseUnsignedInt(pduDataStream);
841d02a064168ae5c916b977182b764580e601cb084Wink Saville            int dataLength = parseUnsignedInt(pduDataStream);
842d02a064168ae5c916b977182b764580e601cb084Wink Saville            PduPart part = new PduPart();
843d02a064168ae5c916b977182b764580e601cb084Wink Saville            int startPos = pduDataStream.available();
844d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (startPos <= 0) {
845d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Invalid part.
846d02a064168ae5c916b977182b764580e601cb084Wink Saville                return null;
847d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
848d02a064168ae5c916b977182b764580e601cb084Wink Saville
849d02a064168ae5c916b977182b764580e601cb084Wink Saville            /* parse part's content-type */
850d02a064168ae5c916b977182b764580e601cb084Wink Saville            HashMap<Integer, Object> map = new HashMap<Integer, Object>();
851d02a064168ae5c916b977182b764580e601cb084Wink Saville            byte[] contentType = parseContentType(pduDataStream, map);
852d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (null != contentType) {
853d02a064168ae5c916b977182b764580e601cb084Wink Saville                part.setContentType(contentType);
854d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else {
855d02a064168ae5c916b977182b764580e601cb084Wink Saville                part.setContentType((PduContentTypes.contentTypes[0]).getBytes()); //"*/*"
856d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
857d02a064168ae5c916b977182b764580e601cb084Wink Saville
858d02a064168ae5c916b977182b764580e601cb084Wink Saville            /* get name parameter */
859d02a064168ae5c916b977182b764580e601cb084Wink Saville            byte[] name = (byte[]) map.get(PduPart.P_NAME);
860d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (null != name) {
861d02a064168ae5c916b977182b764580e601cb084Wink Saville                part.setName(name);
862d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
863d02a064168ae5c916b977182b764580e601cb084Wink Saville
864d02a064168ae5c916b977182b764580e601cb084Wink Saville            /* get charset parameter */
865d02a064168ae5c916b977182b764580e601cb084Wink Saville            Integer charset = (Integer) map.get(PduPart.P_CHARSET);
866d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (null != charset) {
867d02a064168ae5c916b977182b764580e601cb084Wink Saville                part.setCharset(charset);
868d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
869d02a064168ae5c916b977182b764580e601cb084Wink Saville
870d02a064168ae5c916b977182b764580e601cb084Wink Saville            /* parse part's headers */
871d02a064168ae5c916b977182b764580e601cb084Wink Saville            int endPos = pduDataStream.available();
872d02a064168ae5c916b977182b764580e601cb084Wink Saville            int partHeaderLen = headerLength - (startPos - endPos);
873d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (partHeaderLen > 0) {
874d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (false == parsePartHeaders(pduDataStream, part, partHeaderLen)) {
875d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // Parse part header faild.
876d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return null;
877d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
878d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else if (partHeaderLen < 0) {
879d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Invalid length of content-type.
880d02a064168ae5c916b977182b764580e601cb084Wink Saville                return null;
881d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
882d02a064168ae5c916b977182b764580e601cb084Wink Saville
883d02a064168ae5c916b977182b764580e601cb084Wink Saville            /* FIXME: check content-id, name, filename and content location,
884d02a064168ae5c916b977182b764580e601cb084Wink Saville             * if not set anyone of them, generate a default content-location
885d02a064168ae5c916b977182b764580e601cb084Wink Saville             */
886d02a064168ae5c916b977182b764580e601cb084Wink Saville            if ((null == part.getContentLocation())
887d02a064168ae5c916b977182b764580e601cb084Wink Saville                    && (null == part.getName())
888d02a064168ae5c916b977182b764580e601cb084Wink Saville                    && (null == part.getFilename())
889d02a064168ae5c916b977182b764580e601cb084Wink Saville                    && (null == part.getContentId())) {
890d02a064168ae5c916b977182b764580e601cb084Wink Saville                part.setContentLocation(Long.toOctalString(
891d02a064168ae5c916b977182b764580e601cb084Wink Saville                        System.currentTimeMillis()).getBytes());
892d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
893d02a064168ae5c916b977182b764580e601cb084Wink Saville
894d02a064168ae5c916b977182b764580e601cb084Wink Saville            /* get part's data */
895d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (dataLength > 0) {
896d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] partData = new byte[dataLength];
897d02a064168ae5c916b977182b764580e601cb084Wink Saville                String partContentType = new String(part.getContentType());
898d02a064168ae5c916b977182b764580e601cb084Wink Saville                pduDataStream.read(partData, 0, dataLength);
899d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (partContentType.equalsIgnoreCase(ContentType.MULTIPART_ALTERNATIVE)) {
900d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // parse "multipart/vnd.wap.multipart.alternative".
901d02a064168ae5c916b977182b764580e601cb084Wink Saville                    PduBody childBody = parseParts(new ByteArrayInputStream(partData));
902d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // take the first part of children.
903d02a064168ae5c916b977182b764580e601cb084Wink Saville                    part = childBody.getPart(0);
904d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else {
905d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // Check Content-Transfer-Encoding.
906d02a064168ae5c916b977182b764580e601cb084Wink Saville                    byte[] partDataEncoding = part.getContentTransferEncoding();
907d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (null != partDataEncoding) {
908d02a064168ae5c916b977182b764580e601cb084Wink Saville                        String encoding = new String(partDataEncoding);
909d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) {
910d02a064168ae5c916b977182b764580e601cb084Wink Saville                            // Decode "base64" into "binary".
911d02a064168ae5c916b977182b764580e601cb084Wink Saville                            partData = Base64.decodeBase64(partData);
912d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) {
913d02a064168ae5c916b977182b764580e601cb084Wink Saville                            // Decode "quoted-printable" into "binary".
914d02a064168ae5c916b977182b764580e601cb084Wink Saville                            partData = QuotedPrintable.decodeQuotedPrintable(partData);
915d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } else {
916d02a064168ae5c916b977182b764580e601cb084Wink Saville                            // "binary" is the default encoding.
917d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
918d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
919d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (null == partData) {
920d02a064168ae5c916b977182b764580e601cb084Wink Saville                        log("Decode part data error!");
921d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return null;
922d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
923d02a064168ae5c916b977182b764580e601cb084Wink Saville                    part.setData(partData);
924d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
925d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
926d02a064168ae5c916b977182b764580e601cb084Wink Saville
927d02a064168ae5c916b977182b764580e601cb084Wink Saville            /* add this part to body */
928d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (THE_FIRST_PART == checkPartPosition(part)) {
929d02a064168ae5c916b977182b764580e601cb084Wink Saville                /* this is the first part */
930d02a064168ae5c916b977182b764580e601cb084Wink Saville                body.addPart(0, part);
931d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else {
932d02a064168ae5c916b977182b764580e601cb084Wink Saville                /* add the part to the end */
933d02a064168ae5c916b977182b764580e601cb084Wink Saville                body.addPart(part);
934d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
935d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
936d02a064168ae5c916b977182b764580e601cb084Wink Saville
937d02a064168ae5c916b977182b764580e601cb084Wink Saville        return body;
938d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
939d02a064168ae5c916b977182b764580e601cb084Wink Saville
940d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
941d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Log status.
942d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
943d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param text log information
944d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
945d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static void log(String text) {
946d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (LOCAL_LOGV) {
947d02a064168ae5c916b977182b764580e601cb084Wink Saville            Log.v(LOG_TAG, text);
948d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
949d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
950d02a064168ae5c916b977182b764580e601cb084Wink Saville
951d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
952d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse unsigned integer.
953d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
954d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
955d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return the integer, -1 when failed
956d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
957d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static int parseUnsignedInt(ByteArrayInputStream pduDataStream) {
958d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
959d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From wap-230-wsp-20010705-a.pdf
960d02a064168ae5c916b977182b764580e601cb084Wink Saville         * The maximum size of a uintvar is 32 bits.
961d02a064168ae5c916b977182b764580e601cb084Wink Saville         * So it will be encoded in no more than 5 octets.
962d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
963d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
964d02a064168ae5c916b977182b764580e601cb084Wink Saville        int result = 0;
965d02a064168ae5c916b977182b764580e601cb084Wink Saville        int temp = pduDataStream.read();
966d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (temp == -1) {
967d02a064168ae5c916b977182b764580e601cb084Wink Saville            return temp;
968d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
969d02a064168ae5c916b977182b764580e601cb084Wink Saville
970d02a064168ae5c916b977182b764580e601cb084Wink Saville        while((temp & 0x80) != 0) {
971d02a064168ae5c916b977182b764580e601cb084Wink Saville            result = result << 7;
972d02a064168ae5c916b977182b764580e601cb084Wink Saville            result |= temp & 0x7F;
973d02a064168ae5c916b977182b764580e601cb084Wink Saville            temp = pduDataStream.read();
974d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (temp == -1) {
975d02a064168ae5c916b977182b764580e601cb084Wink Saville                return temp;
976d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
977d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
978d02a064168ae5c916b977182b764580e601cb084Wink Saville
979d02a064168ae5c916b977182b764580e601cb084Wink Saville        result = result << 7;
980d02a064168ae5c916b977182b764580e601cb084Wink Saville        result |= temp & 0x7F;
981d02a064168ae5c916b977182b764580e601cb084Wink Saville
982d02a064168ae5c916b977182b764580e601cb084Wink Saville        return result;
983d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
984d02a064168ae5c916b977182b764580e601cb084Wink Saville
985d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
986d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse value length.
987d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
988d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
989d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return the integer
990d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
991d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static int parseValueLength(ByteArrayInputStream pduDataStream) {
992d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
993d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From wap-230-wsp-20010705-a.pdf
994d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Value-length = Short-length | (Length-quote Length)
995d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Short-length = <Any octet 0-30>
996d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Length-quote = <Octet 31>
997d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Length = Uintvar-integer
998d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Uintvar-integer = 1*5 OCTET
999d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1000d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1001d02a064168ae5c916b977182b764580e601cb084Wink Saville        int temp = pduDataStream.read();
1002d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(-1 != temp);
1003d02a064168ae5c916b977182b764580e601cb084Wink Saville        int first = temp & 0xFF;
1004d02a064168ae5c916b977182b764580e601cb084Wink Saville
1005d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (first <= SHORT_LENGTH_MAX) {
1006d02a064168ae5c916b977182b764580e601cb084Wink Saville            return first;
1007d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else if (first == LENGTH_QUOTE) {
1008d02a064168ae5c916b977182b764580e601cb084Wink Saville            return parseUnsignedInt(pduDataStream);
1009d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1010d02a064168ae5c916b977182b764580e601cb084Wink Saville
1011d02a064168ae5c916b977182b764580e601cb084Wink Saville        throw new RuntimeException ("Value length > LENGTH_QUOTE!");
1012d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1013d02a064168ae5c916b977182b764580e601cb084Wink Saville
1014d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1015d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse encoded string value.
1016d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1017d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
1018d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return the EncodedStringValue
1019d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1020d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static EncodedStringValue parseEncodedStringValue(ByteArrayInputStream pduDataStream){
1021d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1022d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From OMA-TS-MMS-ENC-V1_3-20050927-C.pdf
1023d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Encoded-string-value = Text-string | Value-length Char-set Text-string
1024d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1025d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1026d02a064168ae5c916b977182b764580e601cb084Wink Saville        pduDataStream.mark(1);
1027d02a064168ae5c916b977182b764580e601cb084Wink Saville        EncodedStringValue returnValue = null;
1028d02a064168ae5c916b977182b764580e601cb084Wink Saville        int charset = 0;
1029d02a064168ae5c916b977182b764580e601cb084Wink Saville        int temp = pduDataStream.read();
1030d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(-1 != temp);
1031d02a064168ae5c916b977182b764580e601cb084Wink Saville        int first = temp & 0xFF;
1032d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (first == 0) {
1033d02a064168ae5c916b977182b764580e601cb084Wink Saville            return null;    //  Blank subject, bail.
1034d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1035d02a064168ae5c916b977182b764580e601cb084Wink Saville
1036d02a064168ae5c916b977182b764580e601cb084Wink Saville        pduDataStream.reset();
1037d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (first < TEXT_MIN) {
1038d02a064168ae5c916b977182b764580e601cb084Wink Saville            parseValueLength(pduDataStream);
1039d02a064168ae5c916b977182b764580e601cb084Wink Saville
1040d02a064168ae5c916b977182b764580e601cb084Wink Saville            charset = parseShortInteger(pduDataStream); //get the "Charset"
1041d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1042d02a064168ae5c916b977182b764580e601cb084Wink Saville
1043d02a064168ae5c916b977182b764580e601cb084Wink Saville        byte[] textString = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1044d02a064168ae5c916b977182b764580e601cb084Wink Saville
1045d02a064168ae5c916b977182b764580e601cb084Wink Saville        try {
1046d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (0 != charset) {
1047d02a064168ae5c916b977182b764580e601cb084Wink Saville                returnValue = new EncodedStringValue(charset, textString);
1048d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else {
1049d02a064168ae5c916b977182b764580e601cb084Wink Saville                returnValue = new EncodedStringValue(textString);
1050d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1051d02a064168ae5c916b977182b764580e601cb084Wink Saville        } catch(Exception e) {
1052d02a064168ae5c916b977182b764580e601cb084Wink Saville            return null;
1053d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1054d02a064168ae5c916b977182b764580e601cb084Wink Saville
1055d02a064168ae5c916b977182b764580e601cb084Wink Saville        return returnValue;
1056d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1057d02a064168ae5c916b977182b764580e601cb084Wink Saville
1058d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1059d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse Text-String or Quoted-String.
1060d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1061d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
1062d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param stringType TYPE_TEXT_STRING or TYPE_QUOTED_STRING
1063d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return the string without End-of-string in byte array
1064d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1065d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static byte[] parseWapString(ByteArrayInputStream pduDataStream,
1066d02a064168ae5c916b977182b764580e601cb084Wink Saville            int stringType) {
1067d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1068d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1069d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From wap-230-wsp-20010705-a.pdf
1070d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Text-string = [Quote] *TEXT End-of-string
1071d02a064168ae5c916b977182b764580e601cb084Wink Saville         * If the first character in the TEXT is in the range of 128-255,
1072d02a064168ae5c916b977182b764580e601cb084Wink Saville         * a Quote character must precede it.
1073d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Otherwise the Quote character must be omitted.
1074d02a064168ae5c916b977182b764580e601cb084Wink Saville         * The Quote is not part of the contents.
1075d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Quote = <Octet 127>
1076d02a064168ae5c916b977182b764580e601cb084Wink Saville         * End-of-string = <Octet 0>
1077d02a064168ae5c916b977182b764580e601cb084Wink Saville         *
1078d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Quoted-string = <Octet 34> *TEXT End-of-string
1079d02a064168ae5c916b977182b764580e601cb084Wink Saville         *
1080d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Token-text = Token End-of-string
1081d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1082d02a064168ae5c916b977182b764580e601cb084Wink Saville
1083d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Mark supposed beginning of Text-string
1084d02a064168ae5c916b977182b764580e601cb084Wink Saville        // We will have to mark again if first char is QUOTE or QUOTED_STRING_FLAG
1085d02a064168ae5c916b977182b764580e601cb084Wink Saville        pduDataStream.mark(1);
1086d02a064168ae5c916b977182b764580e601cb084Wink Saville
1087d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Check first char
1088d02a064168ae5c916b977182b764580e601cb084Wink Saville        int temp = pduDataStream.read();
1089d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(-1 != temp);
1090d02a064168ae5c916b977182b764580e601cb084Wink Saville        if ((TYPE_QUOTED_STRING == stringType) &&
1091d02a064168ae5c916b977182b764580e601cb084Wink Saville                (QUOTED_STRING_FLAG == temp)) {
1092d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Mark again if QUOTED_STRING_FLAG and ignore it
1093d02a064168ae5c916b977182b764580e601cb084Wink Saville            pduDataStream.mark(1);
1094d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else if ((TYPE_TEXT_STRING == stringType) &&
1095d02a064168ae5c916b977182b764580e601cb084Wink Saville                (QUOTE == temp)) {
1096d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Mark again if QUOTE and ignore it
1097d02a064168ae5c916b977182b764580e601cb084Wink Saville            pduDataStream.mark(1);
1098d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else {
1099d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Otherwise go back to origin
1100d02a064168ae5c916b977182b764580e601cb084Wink Saville            pduDataStream.reset();
1101d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1102d02a064168ae5c916b977182b764580e601cb084Wink Saville
1103d02a064168ae5c916b977182b764580e601cb084Wink Saville        // We are now definitely at the beginning of string
1104d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1105d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Return *TOKEN or *TEXT (Text-String without QUOTE,
1106d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Quoted-String without QUOTED_STRING_FLAG and without End-of-string)
1107d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1108d02a064168ae5c916b977182b764580e601cb084Wink Saville        return getWapString(pduDataStream, stringType);
1109d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1110d02a064168ae5c916b977182b764580e601cb084Wink Saville
1111d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1112d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Check TOKEN data defined in RFC2616.
1113d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param ch checking data
1114d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return true when ch is TOKEN, false when ch is not TOKEN
1115d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1116d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static boolean isTokenCharacter(int ch) {
1117d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1118d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Token      = 1*<any CHAR except CTLs or separators>
1119d02a064168ae5c916b977182b764580e601cb084Wink Saville         * separators = "("(40) | ")"(41) | "<"(60) | ">"(62) | "@"(64)
1120d02a064168ae5c916b977182b764580e601cb084Wink Saville         *            | ","(44) | ";"(59) | ":"(58) | "\"(92) | <">(34)
1121d02a064168ae5c916b977182b764580e601cb084Wink Saville         *            | "/"(47) | "["(91) | "]"(93) | "?"(63) | "="(61)
1122d02a064168ae5c916b977182b764580e601cb084Wink Saville         *            | "{"(123) | "}"(125) | SP(32) | HT(9)
1123d02a064168ae5c916b977182b764580e601cb084Wink Saville         * CHAR       = <any US-ASCII character (octets 0 - 127)>
1124d02a064168ae5c916b977182b764580e601cb084Wink Saville         * CTL        = <any US-ASCII control character
1125d02a064168ae5c916b977182b764580e601cb084Wink Saville         *            (octets 0 - 31) and DEL (127)>
1126d02a064168ae5c916b977182b764580e601cb084Wink Saville         * SP         = <US-ASCII SP, space (32)>
1127d02a064168ae5c916b977182b764580e601cb084Wink Saville         * HT         = <US-ASCII HT, horizontal-tab (9)>
1128d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1129d02a064168ae5c916b977182b764580e601cb084Wink Saville        if((ch < 33) || (ch > 126)) {
1130d02a064168ae5c916b977182b764580e601cb084Wink Saville            return false;
1131d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1132d02a064168ae5c916b977182b764580e601cb084Wink Saville
1133d02a064168ae5c916b977182b764580e601cb084Wink Saville        switch(ch) {
1134d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '"': /* '"' */
1135d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '(': /* '(' */
1136d02a064168ae5c916b977182b764580e601cb084Wink Saville            case ')': /* ')' */
1137d02a064168ae5c916b977182b764580e601cb084Wink Saville            case ',': /* ',' */
1138d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '/': /* '/' */
1139d02a064168ae5c916b977182b764580e601cb084Wink Saville            case ':': /* ':' */
1140d02a064168ae5c916b977182b764580e601cb084Wink Saville            case ';': /* ';' */
1141d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '<': /* '<' */
1142d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '=': /* '=' */
1143d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '>': /* '>' */
1144d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '?': /* '?' */
1145d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '@': /* '@' */
1146d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '[': /* '[' */
1147d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '\\': /* '\' */
1148d02a064168ae5c916b977182b764580e601cb084Wink Saville            case ']': /* ']' */
1149d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '{': /* '{' */
1150d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '}': /* '}' */
1151d02a064168ae5c916b977182b764580e601cb084Wink Saville                return false;
1152d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1153d02a064168ae5c916b977182b764580e601cb084Wink Saville
1154d02a064168ae5c916b977182b764580e601cb084Wink Saville        return true;
1155d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1156d02a064168ae5c916b977182b764580e601cb084Wink Saville
1157d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1158d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Check TEXT data defined in RFC2616.
1159d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param ch checking data
1160d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return true when ch is TEXT, false when ch is not TEXT
1161d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1162d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static boolean isText(int ch) {
1163d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1164d02a064168ae5c916b977182b764580e601cb084Wink Saville         * TEXT = <any OCTET except CTLs,
1165d02a064168ae5c916b977182b764580e601cb084Wink Saville         *      but including LWS>
1166d02a064168ae5c916b977182b764580e601cb084Wink Saville         * CTL  = <any US-ASCII control character
1167d02a064168ae5c916b977182b764580e601cb084Wink Saville         *      (octets 0 - 31) and DEL (127)>
1168d02a064168ae5c916b977182b764580e601cb084Wink Saville         * LWS  = [CRLF] 1*( SP | HT )
1169d02a064168ae5c916b977182b764580e601cb084Wink Saville         * CRLF = CR LF
1170d02a064168ae5c916b977182b764580e601cb084Wink Saville         * CR   = <US-ASCII CR, carriage return (13)>
1171d02a064168ae5c916b977182b764580e601cb084Wink Saville         * LF   = <US-ASCII LF, linefeed (10)>
1172d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1173d02a064168ae5c916b977182b764580e601cb084Wink Saville        if(((ch >= 32) && (ch <= 126)) || ((ch >= 128) && (ch <= 255))) {
1174d02a064168ae5c916b977182b764580e601cb084Wink Saville            return true;
1175d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1176d02a064168ae5c916b977182b764580e601cb084Wink Saville
1177d02a064168ae5c916b977182b764580e601cb084Wink Saville        switch(ch) {
1178d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '\t': /* '\t' */
1179d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '\n': /* '\n' */
1180d02a064168ae5c916b977182b764580e601cb084Wink Saville            case '\r': /* '\r' */
1181d02a064168ae5c916b977182b764580e601cb084Wink Saville                return true;
1182d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1183d02a064168ae5c916b977182b764580e601cb084Wink Saville
1184d02a064168ae5c916b977182b764580e601cb084Wink Saville        return false;
1185d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1186d02a064168ae5c916b977182b764580e601cb084Wink Saville
1187d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static byte[] getWapString(ByteArrayInputStream pduDataStream,
1188d02a064168ae5c916b977182b764580e601cb084Wink Saville            int stringType) {
1189d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1190d02a064168ae5c916b977182b764580e601cb084Wink Saville        ByteArrayOutputStream out = new ByteArrayOutputStream();
1191d02a064168ae5c916b977182b764580e601cb084Wink Saville        int temp = pduDataStream.read();
1192d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(-1 != temp);
1193d02a064168ae5c916b977182b764580e601cb084Wink Saville        while((-1 != temp) && ('\0' != temp)) {
1194d02a064168ae5c916b977182b764580e601cb084Wink Saville            // check each of the character
1195d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (stringType == TYPE_TOKEN_STRING) {
1196d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (isTokenCharacter(temp)) {
1197d02a064168ae5c916b977182b764580e601cb084Wink Saville                    out.write(temp);
1198d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1199d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else {
1200d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (isText(temp)) {
1201d02a064168ae5c916b977182b764580e601cb084Wink Saville                    out.write(temp);
1202d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1203d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1204d02a064168ae5c916b977182b764580e601cb084Wink Saville
1205d02a064168ae5c916b977182b764580e601cb084Wink Saville            temp = pduDataStream.read();
1206d02a064168ae5c916b977182b764580e601cb084Wink Saville            assert(-1 != temp);
1207d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1208d02a064168ae5c916b977182b764580e601cb084Wink Saville
1209d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (out.size() > 0) {
1210d02a064168ae5c916b977182b764580e601cb084Wink Saville            return out.toByteArray();
1211d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1212d02a064168ae5c916b977182b764580e601cb084Wink Saville
1213d02a064168ae5c916b977182b764580e601cb084Wink Saville        return null;
1214d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1215d02a064168ae5c916b977182b764580e601cb084Wink Saville
1216d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1217d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Extract a byte value from the input stream.
1218d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1219d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
1220d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return the byte
1221d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1222d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static int extractByteValue(ByteArrayInputStream pduDataStream) {
1223d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1224d02a064168ae5c916b977182b764580e601cb084Wink Saville        int temp = pduDataStream.read();
1225d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(-1 != temp);
1226d02a064168ae5c916b977182b764580e601cb084Wink Saville        return temp & 0xFF;
1227d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1228d02a064168ae5c916b977182b764580e601cb084Wink Saville
1229d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1230d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse Short-Integer.
1231d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1232d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
1233d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return the byte
1234d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1235d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static int parseShortInteger(ByteArrayInputStream pduDataStream) {
1236d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1237d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From wap-230-wsp-20010705-a.pdf
1238d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Short-integer = OCTET
1239d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Integers in range 0-127 shall be encoded as a one
1240d02a064168ae5c916b977182b764580e601cb084Wink Saville         * octet value with the most significant bit set to one (1xxx xxxx)
1241d02a064168ae5c916b977182b764580e601cb084Wink Saville         * and with the value in the remaining least significant bits.
1242d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1243d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1244d02a064168ae5c916b977182b764580e601cb084Wink Saville        int temp = pduDataStream.read();
1245d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(-1 != temp);
1246d02a064168ae5c916b977182b764580e601cb084Wink Saville        return temp & 0x7F;
1247d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1248d02a064168ae5c916b977182b764580e601cb084Wink Saville
1249d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1250d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse Long-Integer.
1251d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1252d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
1253d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return long integer
1254d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1255d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static long parseLongInteger(ByteArrayInputStream pduDataStream) {
1256d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1257d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From wap-230-wsp-20010705-a.pdf
1258d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Long-integer = Short-length Multi-octet-integer
1259d02a064168ae5c916b977182b764580e601cb084Wink Saville         * The Short-length indicates the length of the Multi-octet-integer
1260d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Multi-octet-integer = 1*30 OCTET
1261d02a064168ae5c916b977182b764580e601cb084Wink Saville         * The content octets shall be an unsigned integer value
1262d02a064168ae5c916b977182b764580e601cb084Wink Saville         * with the most significant octet encoded first (big-endian representation).
1263d02a064168ae5c916b977182b764580e601cb084Wink Saville         * The minimum number of octets must be used to encode the value.
1264d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Short-length = <Any octet 0-30>
1265d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1266d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1267d02a064168ae5c916b977182b764580e601cb084Wink Saville        int temp = pduDataStream.read();
1268d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(-1 != temp);
1269d02a064168ae5c916b977182b764580e601cb084Wink Saville        int count = temp & 0xFF;
1270d02a064168ae5c916b977182b764580e601cb084Wink Saville
1271d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (count > LONG_INTEGER_LENGTH_MAX) {
1272d02a064168ae5c916b977182b764580e601cb084Wink Saville            throw new RuntimeException("Octet count greater than 8 and I can't represent that!");
1273d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1274d02a064168ae5c916b977182b764580e601cb084Wink Saville
1275d02a064168ae5c916b977182b764580e601cb084Wink Saville        long result = 0;
1276d02a064168ae5c916b977182b764580e601cb084Wink Saville
1277d02a064168ae5c916b977182b764580e601cb084Wink Saville        for (int i = 0 ; i < count ; i++) {
1278d02a064168ae5c916b977182b764580e601cb084Wink Saville            temp = pduDataStream.read();
1279d02a064168ae5c916b977182b764580e601cb084Wink Saville            assert(-1 != temp);
1280d02a064168ae5c916b977182b764580e601cb084Wink Saville            result <<= 8;
1281d02a064168ae5c916b977182b764580e601cb084Wink Saville            result += (temp & 0xFF);
1282d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1283d02a064168ae5c916b977182b764580e601cb084Wink Saville
1284d02a064168ae5c916b977182b764580e601cb084Wink Saville        return result;
1285d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1286d02a064168ae5c916b977182b764580e601cb084Wink Saville
1287d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1288d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse Integer-Value.
1289d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1290d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
1291d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return long integer
1292d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1293d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static long parseIntegerValue(ByteArrayInputStream pduDataStream) {
1294d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1295d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From wap-230-wsp-20010705-a.pdf
1296d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Integer-Value = Short-integer | Long-integer
1297d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1298d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1299d02a064168ae5c916b977182b764580e601cb084Wink Saville        pduDataStream.mark(1);
1300d02a064168ae5c916b977182b764580e601cb084Wink Saville        int temp = pduDataStream.read();
1301d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(-1 != temp);
1302d02a064168ae5c916b977182b764580e601cb084Wink Saville        pduDataStream.reset();
1303d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (temp > SHORT_INTEGER_MAX) {
1304d02a064168ae5c916b977182b764580e601cb084Wink Saville            return parseShortInteger(pduDataStream);
1305d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else {
1306d02a064168ae5c916b977182b764580e601cb084Wink Saville            return parseLongInteger(pduDataStream);
1307d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1308d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1309d02a064168ae5c916b977182b764580e601cb084Wink Saville
1310d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1311d02a064168ae5c916b977182b764580e601cb084Wink Saville     * To skip length of the wap value.
1312d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1313d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
1314d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param length area size
1315d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return the values in this area
1316d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1317d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static int skipWapValue(ByteArrayInputStream pduDataStream, int length) {
1318d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1319d02a064168ae5c916b977182b764580e601cb084Wink Saville        byte[] area = new byte[length];
1320d02a064168ae5c916b977182b764580e601cb084Wink Saville        int readLen = pduDataStream.read(area, 0, length);
1321d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (readLen < length) { //The actually read length is lower than the length
1322d02a064168ae5c916b977182b764580e601cb084Wink Saville            return -1;
1323d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else {
1324d02a064168ae5c916b977182b764580e601cb084Wink Saville            return readLen;
1325d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1326d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1327d02a064168ae5c916b977182b764580e601cb084Wink Saville
1328d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1329d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse content type parameters. For now we just support
1330d02a064168ae5c916b977182b764580e601cb084Wink Saville     * four parameters used in mms: "type", "start", "name", "charset".
1331d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1332d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
1333d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param map to store parameters of Content-Type field
1334d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param length length of all the parameters
1335d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1336d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static void parseContentTypeParams(ByteArrayInputStream pduDataStream,
1337d02a064168ae5c916b977182b764580e601cb084Wink Saville            HashMap<Integer, Object> map, Integer length) {
1338d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1339d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From wap-230-wsp-20010705-a.pdf
1340d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Parameter = Typed-parameter | Untyped-parameter
1341d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Typed-parameter = Well-known-parameter-token Typed-value
1342d02a064168ae5c916b977182b764580e601cb084Wink Saville         * the actual expected type of the value is implied by the well-known parameter
1343d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Well-known-parameter-token = Integer-value
1344d02a064168ae5c916b977182b764580e601cb084Wink Saville         * the code values used for parameters are specified in the Assigned Numbers appendix
1345d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Typed-value = Compact-value | Text-value
1346d02a064168ae5c916b977182b764580e601cb084Wink Saville         * In addition to the expected type, there may be no value.
1347d02a064168ae5c916b977182b764580e601cb084Wink Saville         * If the value cannot be encoded using the expected type, it shall be encoded as text.
1348d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Compact-value = Integer-value |
1349d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Date-value | Delta-seconds-value | Q-value | Version-value |
1350d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Uri-value
1351d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Untyped-parameter = Token-text Untyped-value
1352d02a064168ae5c916b977182b764580e601cb084Wink Saville         * the type of the value is unknown, but it shall be encoded as an integer,
1353d02a064168ae5c916b977182b764580e601cb084Wink Saville         * if that is possible.
1354d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Untyped-value = Integer-value | Text-value
1355d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1356d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1357d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(length > 0);
1358d02a064168ae5c916b977182b764580e601cb084Wink Saville
1359d02a064168ae5c916b977182b764580e601cb084Wink Saville        int startPos = pduDataStream.available();
1360d02a064168ae5c916b977182b764580e601cb084Wink Saville        int tempPos = 0;
1361d02a064168ae5c916b977182b764580e601cb084Wink Saville        int lastLen = length;
1362d02a064168ae5c916b977182b764580e601cb084Wink Saville        while(0 < lastLen) {
1363d02a064168ae5c916b977182b764580e601cb084Wink Saville            int param = pduDataStream.read();
1364d02a064168ae5c916b977182b764580e601cb084Wink Saville            assert(-1 != param);
1365d02a064168ae5c916b977182b764580e601cb084Wink Saville            lastLen--;
1366d02a064168ae5c916b977182b764580e601cb084Wink Saville
1367d02a064168ae5c916b977182b764580e601cb084Wink Saville            switch (param) {
1368d02a064168ae5c916b977182b764580e601cb084Wink Saville                /**
1369d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * From rfc2387, chapter 3.1
1370d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * The type parameter must be specified and its value is the MIME media
1371d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * type of the "root" body part. It permits a MIME user agent to
1372d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * determine the content-type without reference to the enclosed body
1373d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * part. If the value of the type parameter and the root body part's
1374d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * content-type differ then the User Agent's behavior is undefined.
1375d02a064168ae5c916b977182b764580e601cb084Wink Saville                 *
1376d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * From wap-230-wsp-20010705-a.pdf
1377d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * type = Constrained-encoding
1378d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * Constrained-encoding = Extension-Media | Short-integer
1379d02a064168ae5c916b977182b764580e601cb084Wink Saville                 * Extension-media = *TEXT End-of-string
1380d02a064168ae5c916b977182b764580e601cb084Wink Saville                 */
1381d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduPart.P_TYPE:
1382d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduPart.P_CT_MR_TYPE:
1383d02a064168ae5c916b977182b764580e601cb084Wink Saville                    pduDataStream.mark(1);
1384d02a064168ae5c916b977182b764580e601cb084Wink Saville                    int first = extractByteValue(pduDataStream);
1385d02a064168ae5c916b977182b764580e601cb084Wink Saville                    pduDataStream.reset();
1386d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (first > TEXT_MAX) {
1387d02a064168ae5c916b977182b764580e601cb084Wink Saville                        // Short-integer (well-known type)
1388d02a064168ae5c916b977182b764580e601cb084Wink Saville                        int index = parseShortInteger(pduDataStream);
1389d02a064168ae5c916b977182b764580e601cb084Wink Saville
1390d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if (index < PduContentTypes.contentTypes.length) {
1391d02a064168ae5c916b977182b764580e601cb084Wink Saville                            byte[] type = (PduContentTypes.contentTypes[index]).getBytes();
1392d02a064168ae5c916b977182b764580e601cb084Wink Saville                            map.put(PduPart.P_TYPE, type);
1393d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } else {
1394d02a064168ae5c916b977182b764580e601cb084Wink Saville                            //not support this type, ignore it.
1395d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
1396d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } else {
1397d02a064168ae5c916b977182b764580e601cb084Wink Saville                        // Text-String (extension-media)
1398d02a064168ae5c916b977182b764580e601cb084Wink Saville                        byte[] type = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1399d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if ((null != type) && (null != map)) {
1400d02a064168ae5c916b977182b764580e601cb084Wink Saville                            map.put(PduPart.P_TYPE, type);
1401d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
1402d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
1403d02a064168ae5c916b977182b764580e601cb084Wink Saville
1404d02a064168ae5c916b977182b764580e601cb084Wink Saville                    tempPos = pduDataStream.available();
1405d02a064168ae5c916b977182b764580e601cb084Wink Saville                    lastLen = length - (startPos - tempPos);
1406d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
1407d02a064168ae5c916b977182b764580e601cb084Wink Saville
1408d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /**
1409d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2.3.
1410d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * Start Parameter Referring to Presentation
1411d02a064168ae5c916b977182b764580e601cb084Wink Saville                     *
1412d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * From rfc2387, chapter 3.2
1413d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * The start parameter, if given, is the content-ID of the compound
1414d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * object's "root". If not present the "root" is the first body part in
1415d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * the Multipart/Related entity. The "root" is the element the
1416d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * applications processes first.
1417d02a064168ae5c916b977182b764580e601cb084Wink Saville                     *
1418d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * From wap-230-wsp-20010705-a.pdf
1419d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * start = Text-String
1420d02a064168ae5c916b977182b764580e601cb084Wink Saville                     */
1421d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduPart.P_START:
1422d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduPart.P_DEP_START:
1423d02a064168ae5c916b977182b764580e601cb084Wink Saville                    byte[] start = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1424d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if ((null != start) && (null != map)) {
1425d02a064168ae5c916b977182b764580e601cb084Wink Saville                        map.put(PduPart.P_START, start);
1426d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
1427d02a064168ae5c916b977182b764580e601cb084Wink Saville
1428d02a064168ae5c916b977182b764580e601cb084Wink Saville                    tempPos = pduDataStream.available();
1429d02a064168ae5c916b977182b764580e601cb084Wink Saville                    lastLen = length - (startPos - tempPos);
1430d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
1431d02a064168ae5c916b977182b764580e601cb084Wink Saville
1432d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /**
1433d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * From oma-ts-mms-conf-v1_3.pdf
1434d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * In creation, the character set SHALL be either us-ascii
1435d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * (IANA MIBenum 3) or utf-8 (IANA MIBenum 106)[Unicode].
1436d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * In retrieval, both us-ascii and utf-8 SHALL be supported.
1437d02a064168ae5c916b977182b764580e601cb084Wink Saville                     *
1438d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * From wap-230-wsp-20010705-a.pdf
1439d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * charset = Well-known-charset|Text-String
1440d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * Well-known-charset = Any-charset | Integer-value
1441d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * Both are encoded using values from Character Set
1442d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * Assignments table in Assigned Numbers
1443d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * Any-charset = <Octet 128>
1444d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * Equivalent to the special RFC2616 charset value "*"
1445d02a064168ae5c916b977182b764580e601cb084Wink Saville                     */
1446d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduPart.P_CHARSET:
1447d02a064168ae5c916b977182b764580e601cb084Wink Saville                    pduDataStream.mark(1);
1448d02a064168ae5c916b977182b764580e601cb084Wink Saville                    int firstValue = extractByteValue(pduDataStream);
1449d02a064168ae5c916b977182b764580e601cb084Wink Saville                    pduDataStream.reset();
1450d02a064168ae5c916b977182b764580e601cb084Wink Saville                    //Check first char
1451d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (((firstValue > TEXT_MIN) && (firstValue < TEXT_MAX)) ||
1452d02a064168ae5c916b977182b764580e601cb084Wink Saville                            (END_STRING_FLAG == firstValue)) {
1453d02a064168ae5c916b977182b764580e601cb084Wink Saville                        //Text-String (extension-charset)
1454d02a064168ae5c916b977182b764580e601cb084Wink Saville                        byte[] charsetStr = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1455d02a064168ae5c916b977182b764580e601cb084Wink Saville                        try {
1456d02a064168ae5c916b977182b764580e601cb084Wink Saville                            int charsetInt = CharacterSets.getMibEnumValue(
1457d02a064168ae5c916b977182b764580e601cb084Wink Saville                                    new String(charsetStr));
1458d02a064168ae5c916b977182b764580e601cb084Wink Saville                            map.put(PduPart.P_CHARSET, charsetInt);
1459d02a064168ae5c916b977182b764580e601cb084Wink Saville                        } catch (UnsupportedEncodingException e) {
1460d02a064168ae5c916b977182b764580e601cb084Wink Saville                            // Not a well-known charset, use "*".
1461d02a064168ae5c916b977182b764580e601cb084Wink Saville                            Log.e(LOG_TAG, Arrays.toString(charsetStr), e);
1462d02a064168ae5c916b977182b764580e601cb084Wink Saville                            map.put(PduPart.P_CHARSET, CharacterSets.ANY_CHARSET);
1463d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
1464d02a064168ae5c916b977182b764580e601cb084Wink Saville                    } else {
1465d02a064168ae5c916b977182b764580e601cb084Wink Saville                        //Well-known-charset
1466d02a064168ae5c916b977182b764580e601cb084Wink Saville                        int charset = (int) parseIntegerValue(pduDataStream);
1467d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if (map != null) {
1468d02a064168ae5c916b977182b764580e601cb084Wink Saville                            map.put(PduPart.P_CHARSET, charset);
1469d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
1470d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
1471d02a064168ae5c916b977182b764580e601cb084Wink Saville
1472d02a064168ae5c916b977182b764580e601cb084Wink Saville                    tempPos = pduDataStream.available();
1473d02a064168ae5c916b977182b764580e601cb084Wink Saville                    lastLen = length - (startPos - tempPos);
1474d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
1475d02a064168ae5c916b977182b764580e601cb084Wink Saville
1476d02a064168ae5c916b977182b764580e601cb084Wink Saville                    /**
1477d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * From oma-ts-mms-conf-v1_3.pdf
1478d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * A name for multipart object SHALL be encoded using name-parameter
1479d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * for Content-Type header in WSP multipart headers.
1480d02a064168ae5c916b977182b764580e601cb084Wink Saville                     *
1481d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * From wap-230-wsp-20010705-a.pdf
1482d02a064168ae5c916b977182b764580e601cb084Wink Saville                     * name = Text-String
1483d02a064168ae5c916b977182b764580e601cb084Wink Saville                     */
1484d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduPart.P_DEP_NAME:
1485d02a064168ae5c916b977182b764580e601cb084Wink Saville                case PduPart.P_NAME:
1486d02a064168ae5c916b977182b764580e601cb084Wink Saville                    byte[] name = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1487d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if ((null != name) && (null != map)) {
1488d02a064168ae5c916b977182b764580e601cb084Wink Saville                        map.put(PduPart.P_NAME, name);
1489d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
1490d02a064168ae5c916b977182b764580e601cb084Wink Saville
1491d02a064168ae5c916b977182b764580e601cb084Wink Saville                    tempPos = pduDataStream.available();
1492d02a064168ae5c916b977182b764580e601cb084Wink Saville                    lastLen = length - (startPos - tempPos);
1493d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
1494d02a064168ae5c916b977182b764580e601cb084Wink Saville                default:
1495d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (LOCAL_LOGV) {
1496d02a064168ae5c916b977182b764580e601cb084Wink Saville                        Log.v(LOG_TAG, "Not supported Content-Type parameter");
1497d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
1498d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (-1 == skipWapValue(pduDataStream, lastLen)) {
1499d02a064168ae5c916b977182b764580e601cb084Wink Saville                    Log.e(LOG_TAG, "Corrupt Content-Type");
1500d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else {
1501d02a064168ae5c916b977182b764580e601cb084Wink Saville                    lastLen = 0;
1502d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1503d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
1504d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1505d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1506d02a064168ae5c916b977182b764580e601cb084Wink Saville
1507d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (0 != lastLen) {
1508d02a064168ae5c916b977182b764580e601cb084Wink Saville            Log.e(LOG_TAG, "Corrupt Content-Type");
1509d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1510d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1511d02a064168ae5c916b977182b764580e601cb084Wink Saville
1512d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1513d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse content type.
1514d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1515d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
1516d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param map to store parameters in Content-Type header field
1517d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return Content-Type value
1518d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1519d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static byte[] parseContentType(ByteArrayInputStream pduDataStream,
1520d02a064168ae5c916b977182b764580e601cb084Wink Saville            HashMap<Integer, Object> map) {
1521d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1522d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From wap-230-wsp-20010705-a.pdf
1523d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Content-type-value = Constrained-media | Content-general-form
1524d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Content-general-form = Value-length Media-type
1525d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Media-type = (Well-known-media | Extension-Media) *(Parameter)
1526d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1527d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1528d02a064168ae5c916b977182b764580e601cb084Wink Saville
1529d02a064168ae5c916b977182b764580e601cb084Wink Saville        byte[] contentType = null;
1530d02a064168ae5c916b977182b764580e601cb084Wink Saville        pduDataStream.mark(1);
1531d02a064168ae5c916b977182b764580e601cb084Wink Saville        int temp = pduDataStream.read();
1532d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(-1 != temp);
1533d02a064168ae5c916b977182b764580e601cb084Wink Saville        pduDataStream.reset();
1534d02a064168ae5c916b977182b764580e601cb084Wink Saville
1535d02a064168ae5c916b977182b764580e601cb084Wink Saville        int cur = (temp & 0xFF);
1536d02a064168ae5c916b977182b764580e601cb084Wink Saville
1537d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (cur < TEXT_MIN) {
1538d02a064168ae5c916b977182b764580e601cb084Wink Saville            int length = parseValueLength(pduDataStream);
1539d02a064168ae5c916b977182b764580e601cb084Wink Saville            int startPos = pduDataStream.available();
1540d02a064168ae5c916b977182b764580e601cb084Wink Saville            pduDataStream.mark(1);
1541d02a064168ae5c916b977182b764580e601cb084Wink Saville            temp = pduDataStream.read();
1542d02a064168ae5c916b977182b764580e601cb084Wink Saville            assert(-1 != temp);
1543d02a064168ae5c916b977182b764580e601cb084Wink Saville            pduDataStream.reset();
1544d02a064168ae5c916b977182b764580e601cb084Wink Saville            int first = (temp & 0xFF);
1545d02a064168ae5c916b977182b764580e601cb084Wink Saville
1546d02a064168ae5c916b977182b764580e601cb084Wink Saville            if ((first >= TEXT_MIN) && (first <= TEXT_MAX)) {
1547d02a064168ae5c916b977182b764580e601cb084Wink Saville                contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1548d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else if (first > TEXT_MAX) {
1549d02a064168ae5c916b977182b764580e601cb084Wink Saville                int index = parseShortInteger(pduDataStream);
1550d02a064168ae5c916b977182b764580e601cb084Wink Saville
1551d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (index < PduContentTypes.contentTypes.length) { //well-known type
1552d02a064168ae5c916b977182b764580e601cb084Wink Saville                    contentType = (PduContentTypes.contentTypes[index]).getBytes();
1553d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else {
1554d02a064168ae5c916b977182b764580e601cb084Wink Saville                    pduDataStream.reset();
1555d02a064168ae5c916b977182b764580e601cb084Wink Saville                    contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1556d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1557d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else {
1558d02a064168ae5c916b977182b764580e601cb084Wink Saville                Log.e(LOG_TAG, "Corrupt content-type");
1559d02a064168ae5c916b977182b764580e601cb084Wink Saville                return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*"
1560d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1561d02a064168ae5c916b977182b764580e601cb084Wink Saville
1562d02a064168ae5c916b977182b764580e601cb084Wink Saville            int endPos = pduDataStream.available();
1563d02a064168ae5c916b977182b764580e601cb084Wink Saville            int parameterLen = length - (startPos - endPos);
1564d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (parameterLen > 0) {//have parameters
1565d02a064168ae5c916b977182b764580e601cb084Wink Saville                parseContentTypeParams(pduDataStream, map, parameterLen);
1566d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1567d02a064168ae5c916b977182b764580e601cb084Wink Saville
1568d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (parameterLen < 0) {
1569d02a064168ae5c916b977182b764580e601cb084Wink Saville                Log.e(LOG_TAG, "Corrupt MMS message");
1570d02a064168ae5c916b977182b764580e601cb084Wink Saville                return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*"
1571d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1572d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else if (cur <= TEXT_MAX) {
1573d02a064168ae5c916b977182b764580e601cb084Wink Saville            contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1574d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else {
1575d02a064168ae5c916b977182b764580e601cb084Wink Saville            contentType =
1576d02a064168ae5c916b977182b764580e601cb084Wink Saville                (PduContentTypes.contentTypes[parseShortInteger(pduDataStream)]).getBytes();
1577d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1578d02a064168ae5c916b977182b764580e601cb084Wink Saville
1579d02a064168ae5c916b977182b764580e601cb084Wink Saville        return contentType;
1580d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1581d02a064168ae5c916b977182b764580e601cb084Wink Saville
1582d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1583d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Parse part's headers.
1584d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1585d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pduDataStream pdu data input stream
1586d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param part to store the header informations of the part
1587d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param length length of the headers
1588d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return true if parse successfully, false otherwise
1589d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1590d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static boolean parsePartHeaders(ByteArrayInputStream pduDataStream,
1591d02a064168ae5c916b977182b764580e601cb084Wink Saville            PduPart part, int length) {
1592d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != pduDataStream);
1593d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != part);
1594d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(length > 0);
1595d02a064168ae5c916b977182b764580e601cb084Wink Saville
1596d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1597d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2.
1598d02a064168ae5c916b977182b764580e601cb084Wink Saville         * A name for multipart object SHALL be encoded using name-parameter
1599d02a064168ae5c916b977182b764580e601cb084Wink Saville         * for Content-Type header in WSP multipart headers.
1600d02a064168ae5c916b977182b764580e601cb084Wink Saville         * In decoding, name-parameter of Content-Type SHALL be used if available.
1601d02a064168ae5c916b977182b764580e601cb084Wink Saville         * If name-parameter of Content-Type is not available,
1602d02a064168ae5c916b977182b764580e601cb084Wink Saville         * filename parameter of Content-Disposition header SHALL be used if available.
1603d02a064168ae5c916b977182b764580e601cb084Wink Saville         * If neither name-parameter of Content-Type header nor filename parameter
1604d02a064168ae5c916b977182b764580e601cb084Wink Saville         * of Content-Disposition header is available,
1605d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Content-Location header SHALL be used if available.
1606d02a064168ae5c916b977182b764580e601cb084Wink Saville         *
1607d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Within SMIL part the reference to the media object parts SHALL use
1608d02a064168ae5c916b977182b764580e601cb084Wink Saville         * either Content-ID or Content-Location mechanism [RFC2557]
1609d02a064168ae5c916b977182b764580e601cb084Wink Saville         * and the corresponding WSP part headers in media object parts
1610d02a064168ae5c916b977182b764580e601cb084Wink Saville         * contain the corresponding definitions.
1611d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1612d02a064168ae5c916b977182b764580e601cb084Wink Saville        int startPos = pduDataStream.available();
1613d02a064168ae5c916b977182b764580e601cb084Wink Saville        int tempPos = 0;
1614d02a064168ae5c916b977182b764580e601cb084Wink Saville        int lastLen = length;
1615d02a064168ae5c916b977182b764580e601cb084Wink Saville        while(0 < lastLen) {
1616d02a064168ae5c916b977182b764580e601cb084Wink Saville            int header = pduDataStream.read();
1617d02a064168ae5c916b977182b764580e601cb084Wink Saville            assert(-1 != header);
1618d02a064168ae5c916b977182b764580e601cb084Wink Saville            lastLen--;
1619d02a064168ae5c916b977182b764580e601cb084Wink Saville
1620d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (header > TEXT_MAX) {
1621d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Number assigned headers.
1622d02a064168ae5c916b977182b764580e601cb084Wink Saville                switch (header) {
1623d02a064168ae5c916b977182b764580e601cb084Wink Saville                    case PduPart.P_CONTENT_LOCATION:
1624d02a064168ae5c916b977182b764580e601cb084Wink Saville                        /**
1625d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
1626d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * Content-location-value = Uri-value
1627d02a064168ae5c916b977182b764580e601cb084Wink Saville                         */
1628d02a064168ae5c916b977182b764580e601cb084Wink Saville                        byte[] contentLocation = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1629d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if (null != contentLocation) {
1630d02a064168ae5c916b977182b764580e601cb084Wink Saville                            part.setContentLocation(contentLocation);
1631d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
1632d02a064168ae5c916b977182b764580e601cb084Wink Saville
1633d02a064168ae5c916b977182b764580e601cb084Wink Saville                        tempPos = pduDataStream.available();
1634d02a064168ae5c916b977182b764580e601cb084Wink Saville                        lastLen = length - (startPos - tempPos);
1635d02a064168ae5c916b977182b764580e601cb084Wink Saville                        break;
1636d02a064168ae5c916b977182b764580e601cb084Wink Saville                    case PduPart.P_CONTENT_ID:
1637d02a064168ae5c916b977182b764580e601cb084Wink Saville                        /**
1638d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
1639d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * Content-ID-value = Quoted-string
1640d02a064168ae5c916b977182b764580e601cb084Wink Saville                         */
1641d02a064168ae5c916b977182b764580e601cb084Wink Saville                        byte[] contentId = parseWapString(pduDataStream, TYPE_QUOTED_STRING);
1642d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if (null != contentId) {
1643d02a064168ae5c916b977182b764580e601cb084Wink Saville                            part.setContentId(contentId);
1644d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
1645d02a064168ae5c916b977182b764580e601cb084Wink Saville
1646d02a064168ae5c916b977182b764580e601cb084Wink Saville                        tempPos = pduDataStream.available();
1647d02a064168ae5c916b977182b764580e601cb084Wink Saville                        lastLen = length - (startPos - tempPos);
1648d02a064168ae5c916b977182b764580e601cb084Wink Saville                        break;
1649d02a064168ae5c916b977182b764580e601cb084Wink Saville                    case PduPart.P_DEP_CONTENT_DISPOSITION:
1650d02a064168ae5c916b977182b764580e601cb084Wink Saville                    case PduPart.P_CONTENT_DISPOSITION:
1651d02a064168ae5c916b977182b764580e601cb084Wink Saville                        /**
1652d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
1653d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * Content-disposition-value = Value-length Disposition *(Parameter)
1654d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * Disposition = Form-data | Attachment | Inline | Token-text
1655d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * Form-data = <Octet 128>
1656d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * Attachment = <Octet 129>
1657d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * Inline = <Octet 130>
1658d02a064168ae5c916b977182b764580e601cb084Wink Saville                         */
1659d02a064168ae5c916b977182b764580e601cb084Wink Saville
1660d02a064168ae5c916b977182b764580e601cb084Wink Saville                        /*
1661d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * some carrier mmsc servers do not support content_disposition
1662d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * field correctly
1663d02a064168ae5c916b977182b764580e601cb084Wink Saville                         */
1664d02a064168ae5c916b977182b764580e601cb084Wink Saville                        boolean contentDisposition = Resources.getSystem().getBoolean(com
1665d02a064168ae5c916b977182b764580e601cb084Wink Saville                                .android.internal.R.bool.config_mms_content_disposition_support);
1666d02a064168ae5c916b977182b764580e601cb084Wink Saville
1667d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if (contentDisposition) {
1668d02a064168ae5c916b977182b764580e601cb084Wink Saville                            int len = parseValueLength(pduDataStream);
1669d02a064168ae5c916b977182b764580e601cb084Wink Saville                            pduDataStream.mark(1);
1670d02a064168ae5c916b977182b764580e601cb084Wink Saville                            int thisStartPos = pduDataStream.available();
1671d02a064168ae5c916b977182b764580e601cb084Wink Saville                            int thisEndPos = 0;
1672d02a064168ae5c916b977182b764580e601cb084Wink Saville                            int value = pduDataStream.read();
1673d02a064168ae5c916b977182b764580e601cb084Wink Saville
1674d02a064168ae5c916b977182b764580e601cb084Wink Saville                            if (value == PduPart.P_DISPOSITION_FROM_DATA ) {
1675d02a064168ae5c916b977182b764580e601cb084Wink Saville                                part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA);
1676d02a064168ae5c916b977182b764580e601cb084Wink Saville                            } else if (value == PduPart.P_DISPOSITION_ATTACHMENT) {
1677d02a064168ae5c916b977182b764580e601cb084Wink Saville                                part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT);
1678d02a064168ae5c916b977182b764580e601cb084Wink Saville                            } else if (value == PduPart.P_DISPOSITION_INLINE) {
1679d02a064168ae5c916b977182b764580e601cb084Wink Saville                                part.setContentDisposition(PduPart.DISPOSITION_INLINE);
1680d02a064168ae5c916b977182b764580e601cb084Wink Saville                            } else {
1681d02a064168ae5c916b977182b764580e601cb084Wink Saville                                pduDataStream.reset();
1682d02a064168ae5c916b977182b764580e601cb084Wink Saville                                /* Token-text */
1683d02a064168ae5c916b977182b764580e601cb084Wink Saville                                part.setContentDisposition(parseWapString(pduDataStream
1684d02a064168ae5c916b977182b764580e601cb084Wink Saville                                        , TYPE_TEXT_STRING));
1685d02a064168ae5c916b977182b764580e601cb084Wink Saville                            }
1686d02a064168ae5c916b977182b764580e601cb084Wink Saville
1687d02a064168ae5c916b977182b764580e601cb084Wink Saville                            /* get filename parameter and skip other parameters */
1688d02a064168ae5c916b977182b764580e601cb084Wink Saville                            thisEndPos = pduDataStream.available();
1689d02a064168ae5c916b977182b764580e601cb084Wink Saville                            if (thisStartPos - thisEndPos < len) {
1690d02a064168ae5c916b977182b764580e601cb084Wink Saville                                value = pduDataStream.read();
1691d02a064168ae5c916b977182b764580e601cb084Wink Saville                                if (value == PduPart.P_FILENAME) { //filename is text-string
1692d02a064168ae5c916b977182b764580e601cb084Wink Saville                                    part.setFilename(parseWapString(pduDataStream
1693d02a064168ae5c916b977182b764580e601cb084Wink Saville                                            , TYPE_TEXT_STRING));
1694d02a064168ae5c916b977182b764580e601cb084Wink Saville                                }
1695d02a064168ae5c916b977182b764580e601cb084Wink Saville
1696d02a064168ae5c916b977182b764580e601cb084Wink Saville                                /* skip other parameters */
1697d02a064168ae5c916b977182b764580e601cb084Wink Saville                                thisEndPos = pduDataStream.available();
1698d02a064168ae5c916b977182b764580e601cb084Wink Saville                                if (thisStartPos - thisEndPos < len) {
1699d02a064168ae5c916b977182b764580e601cb084Wink Saville                                    int last = len - (thisStartPos - thisEndPos);
1700d02a064168ae5c916b977182b764580e601cb084Wink Saville                                    byte[] temp = new byte[last];
1701d02a064168ae5c916b977182b764580e601cb084Wink Saville                                    pduDataStream.read(temp, 0, last);
1702d02a064168ae5c916b977182b764580e601cb084Wink Saville                                }
1703d02a064168ae5c916b977182b764580e601cb084Wink Saville                            }
1704d02a064168ae5c916b977182b764580e601cb084Wink Saville
1705d02a064168ae5c916b977182b764580e601cb084Wink Saville                            tempPos = pduDataStream.available();
1706d02a064168ae5c916b977182b764580e601cb084Wink Saville                            lastLen = length - (startPos - tempPos);
1707d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
1708d02a064168ae5c916b977182b764580e601cb084Wink Saville                        break;
1709d02a064168ae5c916b977182b764580e601cb084Wink Saville                    default:
1710d02a064168ae5c916b977182b764580e601cb084Wink Saville                        if (LOCAL_LOGV) {
1711d02a064168ae5c916b977182b764580e601cb084Wink Saville                            Log.v(LOG_TAG, "Not supported Part headers: " + header);
1712d02a064168ae5c916b977182b764580e601cb084Wink Saville                        }
1713d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (-1 == skipWapValue(pduDataStream, lastLen)) {
1714d02a064168ae5c916b977182b764580e601cb084Wink Saville                        Log.e(LOG_TAG, "Corrupt Part headers");
1715d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return false;
1716d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
1717d02a064168ae5c916b977182b764580e601cb084Wink Saville                    lastLen = 0;
1718d02a064168ae5c916b977182b764580e601cb084Wink Saville                    break;
1719d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1720d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else if ((header >= TEXT_MIN) && (header <= TEXT_MAX)) {
1721d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Not assigned header.
1722d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] tempHeader = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1723d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] tempValue = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1724d02a064168ae5c916b977182b764580e601cb084Wink Saville
1725d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Check the header whether it is "Content-Transfer-Encoding".
1726d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (true ==
1727d02a064168ae5c916b977182b764580e601cb084Wink Saville                    PduPart.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(new String(tempHeader))) {
1728d02a064168ae5c916b977182b764580e601cb084Wink Saville                    part.setContentTransferEncoding(tempValue);
1729d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1730d02a064168ae5c916b977182b764580e601cb084Wink Saville
1731d02a064168ae5c916b977182b764580e601cb084Wink Saville                tempPos = pduDataStream.available();
1732d02a064168ae5c916b977182b764580e601cb084Wink Saville                lastLen = length - (startPos - tempPos);
1733d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else {
1734d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (LOCAL_LOGV) {
1735d02a064168ae5c916b977182b764580e601cb084Wink Saville                    Log.v(LOG_TAG, "Not supported Part headers: " + header);
1736d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1737d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Skip all headers of this part.
1738d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (-1 == skipWapValue(pduDataStream, lastLen)) {
1739d02a064168ae5c916b977182b764580e601cb084Wink Saville                    Log.e(LOG_TAG, "Corrupt Part headers");
1740d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1741d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1742d02a064168ae5c916b977182b764580e601cb084Wink Saville                lastLen = 0;
1743d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1744d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1745d02a064168ae5c916b977182b764580e601cb084Wink Saville
1746d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (0 != lastLen) {
1747d02a064168ae5c916b977182b764580e601cb084Wink Saville            Log.e(LOG_TAG, "Corrupt Part headers");
1748d02a064168ae5c916b977182b764580e601cb084Wink Saville            return false;
1749d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1750d02a064168ae5c916b977182b764580e601cb084Wink Saville
1751d02a064168ae5c916b977182b764580e601cb084Wink Saville        return true;
1752d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1753d02a064168ae5c916b977182b764580e601cb084Wink Saville
1754d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1755d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Check the position of a specified part.
1756d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1757d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param part the part to be checked
1758d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return part position, THE_FIRST_PART when it's the
1759d02a064168ae5c916b977182b764580e601cb084Wink Saville     * first one, THE_LAST_PART when it's the last one.
1760d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1761d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static int checkPartPosition(PduPart part) {
1762d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(null != part);
1763d02a064168ae5c916b977182b764580e601cb084Wink Saville        if ((null == mTypeParam) &&
1764d02a064168ae5c916b977182b764580e601cb084Wink Saville                (null == mStartParam)) {
1765d02a064168ae5c916b977182b764580e601cb084Wink Saville            return THE_LAST_PART;
1766d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1767d02a064168ae5c916b977182b764580e601cb084Wink Saville
1768d02a064168ae5c916b977182b764580e601cb084Wink Saville        /* check part's content-id */
1769d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (null != mStartParam) {
1770d02a064168ae5c916b977182b764580e601cb084Wink Saville            byte[] contentId = part.getContentId();
1771d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (null != contentId) {
1772d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (true == Arrays.equals(mStartParam, contentId)) {
1773d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return THE_FIRST_PART;
1774d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1775d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1776d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1777d02a064168ae5c916b977182b764580e601cb084Wink Saville
1778d02a064168ae5c916b977182b764580e601cb084Wink Saville        /* check part's content-type */
1779d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (null != mTypeParam) {
1780d02a064168ae5c916b977182b764580e601cb084Wink Saville            byte[] contentType = part.getContentType();
1781d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (null != contentType) {
1782d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (true == Arrays.equals(mTypeParam, contentType)) {
1783d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return THE_FIRST_PART;
1784d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1785d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1786d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1787d02a064168ae5c916b977182b764580e601cb084Wink Saville
1788d02a064168ae5c916b977182b764580e601cb084Wink Saville        return THE_LAST_PART;
1789d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1790d02a064168ae5c916b977182b764580e601cb084Wink Saville
1791d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1792d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Check mandatory headers of a pdu.
1793d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1794d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param headers pdu headers
1795d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return true if the pdu has all of the mandatory headers, false otherwise.
1796d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1797d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static boolean checkMandatoryHeader(PduHeaders headers) {
1798d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (null == headers) {
1799d02a064168ae5c916b977182b764580e601cb084Wink Saville            return false;
1800d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1801d02a064168ae5c916b977182b764580e601cb084Wink Saville
1802d02a064168ae5c916b977182b764580e601cb084Wink Saville        /* get message type */
1803d02a064168ae5c916b977182b764580e601cb084Wink Saville        int messageType = headers.getOctet(PduHeaders.MESSAGE_TYPE);
1804d02a064168ae5c916b977182b764580e601cb084Wink Saville
1805d02a064168ae5c916b977182b764580e601cb084Wink Saville        /* check Mms-Version field */
1806d02a064168ae5c916b977182b764580e601cb084Wink Saville        int mmsVersion = headers.getOctet(PduHeaders.MMS_VERSION);
1807d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (0 == mmsVersion) {
1808d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Every message should have Mms-Version field.
1809d02a064168ae5c916b977182b764580e601cb084Wink Saville            return false;
1810d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1811d02a064168ae5c916b977182b764580e601cb084Wink Saville
1812d02a064168ae5c916b977182b764580e601cb084Wink Saville        /* check mandatory header fields */
1813d02a064168ae5c916b977182b764580e601cb084Wink Saville        switch (messageType) {
1814d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
1815d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Content-Type field.
1816d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] srContentType = headers.getTextString(PduHeaders.CONTENT_TYPE);
1817d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == srContentType) {
1818d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1819d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1820d02a064168ae5c916b977182b764580e601cb084Wink Saville
1821d02a064168ae5c916b977182b764580e601cb084Wink Saville                // From field.
1822d02a064168ae5c916b977182b764580e601cb084Wink Saville                EncodedStringValue srFrom = headers.getEncodedStringValue(PduHeaders.FROM);
1823d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == srFrom) {
1824d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1825d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1826d02a064168ae5c916b977182b764580e601cb084Wink Saville
1827d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Transaction-Id field.
1828d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] srTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
1829d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == srTransactionId) {
1830d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1831d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1832d02a064168ae5c916b977182b764580e601cb084Wink Saville
1833d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
1834d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_SEND_CONF:
1835d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Response-Status field.
1836d02a064168ae5c916b977182b764580e601cb084Wink Saville                int scResponseStatus = headers.getOctet(PduHeaders.RESPONSE_STATUS);
1837d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (0 == scResponseStatus) {
1838d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1839d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1840d02a064168ae5c916b977182b764580e601cb084Wink Saville
1841d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Transaction-Id field.
1842d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] scTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
1843d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == scTransactionId) {
1844d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1845d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1846d02a064168ae5c916b977182b764580e601cb084Wink Saville
1847d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
1848d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
1849d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Content-Location field.
1850d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] niContentLocation = headers.getTextString(PduHeaders.CONTENT_LOCATION);
1851d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == niContentLocation) {
1852d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1853d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1854d02a064168ae5c916b977182b764580e601cb084Wink Saville
1855d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Expiry field.
1856d02a064168ae5c916b977182b764580e601cb084Wink Saville                long niExpiry = headers.getLongInteger(PduHeaders.EXPIRY);
1857d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (-1 == niExpiry) {
1858d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1859d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1860d02a064168ae5c916b977182b764580e601cb084Wink Saville
1861d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Message-Class field.
1862d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] niMessageClass = headers.getTextString(PduHeaders.MESSAGE_CLASS);
1863d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == niMessageClass) {
1864d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1865d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1866d02a064168ae5c916b977182b764580e601cb084Wink Saville
1867d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Message-Size field.
1868d02a064168ae5c916b977182b764580e601cb084Wink Saville                long niMessageSize = headers.getLongInteger(PduHeaders.MESSAGE_SIZE);
1869d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (-1 == niMessageSize) {
1870d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1871d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1872d02a064168ae5c916b977182b764580e601cb084Wink Saville
1873d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Transaction-Id field.
1874d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] niTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
1875d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == niTransactionId) {
1876d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1877d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1878d02a064168ae5c916b977182b764580e601cb084Wink Saville
1879d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
1880d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
1881d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Status field.
1882d02a064168ae5c916b977182b764580e601cb084Wink Saville                int nriStatus = headers.getOctet(PduHeaders.STATUS);
1883d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (0 == nriStatus) {
1884d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1885d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1886d02a064168ae5c916b977182b764580e601cb084Wink Saville
1887d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Transaction-Id field.
1888d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] nriTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
1889d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == nriTransactionId) {
1890d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1891d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1892d02a064168ae5c916b977182b764580e601cb084Wink Saville
1893d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
1894d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
1895d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Content-Type field.
1896d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] rcContentType = headers.getTextString(PduHeaders.CONTENT_TYPE);
1897d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == rcContentType) {
1898d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1899d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1900d02a064168ae5c916b977182b764580e601cb084Wink Saville
1901d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Date field.
1902d02a064168ae5c916b977182b764580e601cb084Wink Saville                long rcDate = headers.getLongInteger(PduHeaders.DATE);
1903d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (-1 == rcDate) {
1904d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1905d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1906d02a064168ae5c916b977182b764580e601cb084Wink Saville
1907d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
1908d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
1909d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Date field.
1910d02a064168ae5c916b977182b764580e601cb084Wink Saville                long diDate = headers.getLongInteger(PduHeaders.DATE);
1911d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (-1 == diDate) {
1912d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1913d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1914d02a064168ae5c916b977182b764580e601cb084Wink Saville
1915d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Message-Id field.
1916d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] diMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
1917d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == diMessageId) {
1918d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1919d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1920d02a064168ae5c916b977182b764580e601cb084Wink Saville
1921d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Status field.
1922d02a064168ae5c916b977182b764580e601cb084Wink Saville                int diStatus = headers.getOctet(PduHeaders.STATUS);
1923d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (0 == diStatus) {
1924d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1925d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1926d02a064168ae5c916b977182b764580e601cb084Wink Saville
1927d02a064168ae5c916b977182b764580e601cb084Wink Saville                // To field.
1928d02a064168ae5c916b977182b764580e601cb084Wink Saville                EncodedStringValue[] diTo = headers.getEncodedStringValues(PduHeaders.TO);
1929d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == diTo) {
1930d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1931d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1932d02a064168ae5c916b977182b764580e601cb084Wink Saville
1933d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
1934d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
1935d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Transaction-Id field.
1936d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] aiTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
1937d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == aiTransactionId) {
1938d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1939d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1940d02a064168ae5c916b977182b764580e601cb084Wink Saville
1941d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
1942d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
1943d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Date field.
1944d02a064168ae5c916b977182b764580e601cb084Wink Saville                long roDate = headers.getLongInteger(PduHeaders.DATE);
1945d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (-1 == roDate) {
1946d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1947d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1948d02a064168ae5c916b977182b764580e601cb084Wink Saville
1949d02a064168ae5c916b977182b764580e601cb084Wink Saville                // From field.
1950d02a064168ae5c916b977182b764580e601cb084Wink Saville                EncodedStringValue roFrom = headers.getEncodedStringValue(PduHeaders.FROM);
1951d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == roFrom) {
1952d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1953d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1954d02a064168ae5c916b977182b764580e601cb084Wink Saville
1955d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Message-Id field.
1956d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] roMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
1957d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == roMessageId) {
1958d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1959d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1960d02a064168ae5c916b977182b764580e601cb084Wink Saville
1961d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Read-Status field.
1962d02a064168ae5c916b977182b764580e601cb084Wink Saville                int roReadStatus = headers.getOctet(PduHeaders.READ_STATUS);
1963d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (0 == roReadStatus) {
1964d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1965d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1966d02a064168ae5c916b977182b764580e601cb084Wink Saville
1967d02a064168ae5c916b977182b764580e601cb084Wink Saville                // To field.
1968d02a064168ae5c916b977182b764580e601cb084Wink Saville                EncodedStringValue[] roTo = headers.getEncodedStringValues(PduHeaders.TO);
1969d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == roTo) {
1970d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1971d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1972d02a064168ae5c916b977182b764580e601cb084Wink Saville
1973d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
1974d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
1975d02a064168ae5c916b977182b764580e601cb084Wink Saville                // From field.
1976d02a064168ae5c916b977182b764580e601cb084Wink Saville                EncodedStringValue rrFrom = headers.getEncodedStringValue(PduHeaders.FROM);
1977d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == rrFrom) {
1978d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1979d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1980d02a064168ae5c916b977182b764580e601cb084Wink Saville
1981d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Message-Id field.
1982d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] rrMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
1983d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == rrMessageId) {
1984d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1985d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1986d02a064168ae5c916b977182b764580e601cb084Wink Saville
1987d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Read-Status field.
1988d02a064168ae5c916b977182b764580e601cb084Wink Saville                int rrReadStatus = headers.getOctet(PduHeaders.READ_STATUS);
1989d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (0 == rrReadStatus) {
1990d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1991d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1992d02a064168ae5c916b977182b764580e601cb084Wink Saville
1993d02a064168ae5c916b977182b764580e601cb084Wink Saville                // To field.
1994d02a064168ae5c916b977182b764580e601cb084Wink Saville                EncodedStringValue[] rrTo = headers.getEncodedStringValues(PduHeaders.TO);
1995d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == rrTo) {
1996d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return false;
1997d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1998d02a064168ae5c916b977182b764580e601cb084Wink Saville
1999d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
2000d02a064168ae5c916b977182b764580e601cb084Wink Saville            default:
2001d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Parser doesn't support this message type in this version.
2002d02a064168ae5c916b977182b764580e601cb084Wink Saville                return false;
2003d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
2004d02a064168ae5c916b977182b764580e601cb084Wink Saville
2005d02a064168ae5c916b977182b764580e601cb084Wink Saville        return true;
2006d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
2007d02a064168ae5c916b977182b764580e601cb084Wink Saville}
2008