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