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