1526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen/*
2526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Copyright (C) 2007-2008 Esmertec AG.
3526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Copyright (C) 2007-2008 The Android Open Source Project
4526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *
5526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Licensed under the Apache License, Version 2.0 (the "License");
6526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * you may not use this file except in compliance with the License.
7526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * You may obtain a copy of the License at
8526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *
9526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *      http://www.apache.org/licenses/LICENSE-2.0
10526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen *
11526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * Unless required by applicable law or agreed to in writing, software
12526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * distributed under the License is distributed on an "AS IS" BASIS,
13526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * See the License for the specific language governing permissions and
15526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen * limitations under the License.
16526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen */
17526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
18526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenpackage com.google.android.mms.pdu;
19526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
20032e0398ba2770edd52c543482afbae6f92ff29bYe Wenimport android.util.Log;
21032e0398ba2770edd52c543482afbae6f92ff29bYe Wen
22526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport com.google.android.mms.ContentType;
23526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport com.google.android.mms.InvalidHeaderValueException;
24526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
25526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport java.io.ByteArrayInputStream;
26526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport java.io.ByteArrayOutputStream;
27526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport java.io.UnsupportedEncodingException;
28526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport java.util.Arrays;
29526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenimport java.util.HashMap;
30526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
31526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wenpublic class PduParser {
32526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
33526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *  The next are WAP values defined in WSP specification.
34526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
35526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int QUOTE = 127;
36526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int LENGTH_QUOTE = 31;
37526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int TEXT_MIN = 32;
38526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int TEXT_MAX = 127;
39526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int SHORT_INTEGER_MAX = 127;
40526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int SHORT_LENGTH_MAX = 30;
41526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int LONG_INTEGER_LENGTH_MAX = 8;
42526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int QUOTED_STRING_FLAG = 34;
43526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int END_STRING_FLAG = 0x00;
44526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    //The next two are used by the interface "parseWapString" to
45526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    //distinguish Text-String and Quoted-String.
46526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int TYPE_TEXT_STRING = 0;
47526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int TYPE_QUOTED_STRING = 1;
48526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int TYPE_TOKEN_STRING = 2;
49526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
50526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
51526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Specify the part position.
52526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
53526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int THE_FIRST_PART = 0;
54526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final int THE_LAST_PART = 1;
55526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
56526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
57526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * The pdu data.
58526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
59526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private ByteArrayInputStream mPduDataStream = null;
60526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
61526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
62526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Store pdu headers
63526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
64526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private PduHeaders mHeaders = null;
65526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
66526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
67526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Store pdu parts.
68526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
69526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private PduBody mBody = null;
70526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
71526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
72526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Store the "type" parameter in "Content-Type" header field.
73526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
74526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static byte[] mTypeParam = null;
75526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
76526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
77526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Store the "start" parameter in "Content-Type" header field.
78526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
79526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static byte[] mStartParam = null;
80526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
81526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
82526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * The log tag.
83526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
84526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final String LOG_TAG = "PduParser";
85526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final boolean DEBUG = false;
86526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static final boolean LOCAL_LOGV = false;
87526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
88526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
89032e0398ba2770edd52c543482afbae6f92ff29bYe Wen     * Whether to parse content-disposition part header
90032e0398ba2770edd52c543482afbae6f92ff29bYe Wen     */
91032e0398ba2770edd52c543482afbae6f92ff29bYe Wen    private final boolean mParseContentDisposition;
92032e0398ba2770edd52c543482afbae6f92ff29bYe Wen
93032e0398ba2770edd52c543482afbae6f92ff29bYe Wen    /**
94526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Constructor.
95526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
96526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data to be parsed
97032e0398ba2770edd52c543482afbae6f92ff29bYe Wen     * @param parseContentDisposition whether to parse the Content-Disposition part header
98526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
99032e0398ba2770edd52c543482afbae6f92ff29bYe Wen    public PduParser(byte[] pduDataStream, boolean parseContentDisposition) {
100526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        mPduDataStream = new ByteArrayInputStream(pduDataStream);
101032e0398ba2770edd52c543482afbae6f92ff29bYe Wen        mParseContentDisposition = parseContentDisposition;
102526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
103526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
104526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
105526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse the pdu.
106526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
107526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return the pdu structure if parsing successfully.
108526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *         null if parsing error happened or mandatory fields are not set.
109526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
110526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    public GenericPdu parse(){
111526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (mPduDataStream == null) {
112526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return null;
113526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
114526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
115526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /* parse headers */
116526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        mHeaders = parseHeaders(mPduDataStream);
117526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (null == mHeaders) {
118526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            // Parse headers failed.
119526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return null;
120526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
121526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
122526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /* get the message type */
123526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int messageType = mHeaders.getOctet(PduHeaders.MESSAGE_TYPE);
124526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
125526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /* check mandatory header fields */
126526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (false == checkMandatoryHeader(mHeaders)) {
127526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            log("check mandatory headers failed!");
128526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return null;
129526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
130526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
131526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if ((PduHeaders.MESSAGE_TYPE_SEND_REQ == messageType) ||
132526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                (PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF == messageType)) {
133526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            /* need to parse the parts */
134526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            mBody = parseParts(mPduDataStream);
135526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (null == mBody) {
136526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Parse parts failed.
137526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return null;
138526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
139526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
140526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
141526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        switch (messageType) {
142526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
143526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (LOCAL_LOGV) {
144526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_SEND_REQ");
145526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
146526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                SendReq sendReq = new SendReq(mHeaders, mBody);
147526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return sendReq;
148526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_SEND_CONF:
149526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (LOCAL_LOGV) {
150526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_SEND_CONF");
151526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
152526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                SendConf sendConf = new SendConf(mHeaders);
153526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return sendConf;
154526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
155526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (LOCAL_LOGV) {
156526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_NOTIFICATION_IND");
157526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
158526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                NotificationInd notificationInd =
159526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    new NotificationInd(mHeaders);
160526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return notificationInd;
161526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
162526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (LOCAL_LOGV) {
163526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_NOTIFYRESP_IND");
164526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
165526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                NotifyRespInd notifyRespInd =
166526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    new NotifyRespInd(mHeaders);
167526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return notifyRespInd;
168526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
169526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (LOCAL_LOGV) {
170526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_RETRIEVE_CONF");
171526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
172526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                RetrieveConf retrieveConf =
173526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    new RetrieveConf(mHeaders, mBody);
174526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
175526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] contentType = retrieveConf.getContentType();
176526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == contentType) {
177526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return null;
178526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
179526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                String ctTypeStr = new String(contentType);
180526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (ctTypeStr.equals(ContentType.MULTIPART_MIXED)
181526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        || ctTypeStr.equals(ContentType.MULTIPART_RELATED)
182526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        || ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
183526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    // The MMS content type must be "application/vnd.wap.multipart.mixed"
184526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    // or "application/vnd.wap.multipart.related"
185526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    // or "application/vnd.wap.multipart.alternative"
186526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return retrieveConf;
187526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                } else if (ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
188526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    // "application/vnd.wap.multipart.alternative"
189526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    // should take only the first part.
190526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    PduPart firstPart = mBody.getPart(0);
191526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    mBody.removeAll();
192526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    mBody.addPart(0, firstPart);
193526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return retrieveConf;
194526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
195526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return null;
196526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
197526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (LOCAL_LOGV) {
198526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_DELIVERY_IND");
199526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
200526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                DeliveryInd deliveryInd =
201526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    new DeliveryInd(mHeaders);
202526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return deliveryInd;
203526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
204526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (LOCAL_LOGV) {
205526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_ACKNOWLEDGE_IND");
206526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
207526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                AcknowledgeInd acknowledgeInd =
208526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    new AcknowledgeInd(mHeaders);
209526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return acknowledgeInd;
210526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
211526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (LOCAL_LOGV) {
212526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_READ_ORIG_IND");
213526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
214526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                ReadOrigInd readOrigInd =
215526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    new ReadOrigInd(mHeaders);
216526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return readOrigInd;
217526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
218526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (LOCAL_LOGV) {
219526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.v(LOG_TAG, "parse: MESSAGE_TYPE_READ_REC_IND");
220526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
221526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                ReadRecInd readRecInd =
222526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    new ReadRecInd(mHeaders);
223526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return readRecInd;
224526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            default:
225526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                log("Parser doesn't support this message type in this version!");
226526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return null;
227526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
228526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
229526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
230526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
231526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse pdu headers.
232526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
233526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
234526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return headers in PduHeaders structure, null when parse fail
235526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
236526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected PduHeaders parseHeaders(ByteArrayInputStream pduDataStream){
237526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (pduDataStream == null) {
238526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return null;
239526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
240526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        boolean keepParsing = true;
241526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        PduHeaders headers = new PduHeaders();
242526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
243526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        while (keepParsing && (pduDataStream.available() > 0)) {
244526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            pduDataStream.mark(1);
245526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int headerField = extractByteValue(pduDataStream);
246526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            /* parse custom text header */
247526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if ((headerField >= TEXT_MIN) && (headerField <= TEXT_MAX)) {
248526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                pduDataStream.reset();
249526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte [] bVal = parseWapString(pduDataStream, TYPE_TEXT_STRING);
250526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (LOCAL_LOGV) {
251526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.v(LOG_TAG, "TextHeader: " + new String(bVal));
252526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
253526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /* we should ignore it at the moment */
254526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                continue;
255526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
256526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            switch (headerField) {
257526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.MESSAGE_TYPE:
258526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                {
259526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    int messageType = extractByteValue(pduDataStream);
260526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (LOCAL_LOGV) {
261526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.v(LOG_TAG, "parseHeaders: messageType: " + messageType);
262526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
263526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    switch (messageType) {
264526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        // We don't support these kind of messages now.
265526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_FORWARD_REQ:
266526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_FORWARD_CONF:
267526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ:
268526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF:
269526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ:
270526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF:
271526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ:
272526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF:
273526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ:
274526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF:
275526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_MBOX_DESCR:
276526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_DELETE_REQ:
277526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_DELETE_CONF:
278526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_CANCEL_REQ:
279526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        case PduHeaders.MESSAGE_TYPE_CANCEL_CONF:
280526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            return null;
281526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
282526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
283526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        headers.setOctet(messageType, headerField);
284526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(InvalidHeaderValueException e) {
285526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log("Set invalid Octet value: " + messageType +
286526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                " into the header filed: " + headerField);
287526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
288526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
289526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + "is not Octet header field!");
290526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
291526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
292526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
293526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
294526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /* Octect value */
295526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.REPORT_ALLOWED:
296526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.ADAPTATION_ALLOWED:
297526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.DELIVERY_REPORT:
298526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.DRM_CONTENT:
299526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.DISTRIBUTION_INDICATOR:
300526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.QUOTAS:
301526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.READ_REPORT:
302526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.STORE:
303526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.STORED:
304526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.TOTALS:
305526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.SENDER_VISIBILITY:
306526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.READ_STATUS:
307526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.CANCEL_STATUS:
308526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.PRIORITY:
309526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.STATUS:
310526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.REPLY_CHARGING:
311526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.MM_STATE:
312526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.RECOMMENDED_RETRIEVAL_MODE:
313526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.CONTENT_CLASS:
314526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.RETRIEVE_STATUS:
315526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.STORE_STATUS:
316526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /**
317526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * The following field has a different value when
318526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * used in the M-Mbox-Delete.conf and M-Delete.conf PDU.
319526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * For now we ignore this fact, since we do not support these PDUs
320526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     */
321526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.RESPONSE_STATUS:
322526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                {
323526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    int value = extractByteValue(pduDataStream);
324526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (LOCAL_LOGV) {
325526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.v(LOG_TAG, "parseHeaders: byte: " + headerField + " value: " +
326526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                value);
327526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
328526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
329526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
330526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        headers.setOctet(value, headerField);
331526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(InvalidHeaderValueException e) {
332526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log("Set invalid Octet value: " + value +
333526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                " into the header filed: " + headerField);
334526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
335526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
336526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + "is not Octet header field!");
337526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
338526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
339526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
340526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
341526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
342526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /* Long-Integer */
343526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.DATE:
344526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.REPLY_CHARGING_SIZE:
345526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.MESSAGE_SIZE:
346526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                {
347526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
348526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        long value = parseLongInteger(pduDataStream);
349526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (LOCAL_LOGV) {
350526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            Log.v(LOG_TAG, "parseHeaders: longint: " + headerField + " value: " +
351526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    value);
352526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
353526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        headers.setLongInteger(value, headerField);
354526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
355526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + "is not Long-Integer header field!");
356526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
357526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
358526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
359526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
360526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
361526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /* Integer-Value */
362526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.MESSAGE_COUNT:
363526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.START:
364526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.LIMIT:
365526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                {
366526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
367526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        long value = parseIntegerValue(pduDataStream);
368526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (LOCAL_LOGV) {
369526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            Log.v(LOG_TAG, "parseHeaders: int: " + headerField + " value: " +
370526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    value);
371526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
372526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        headers.setLongInteger(value, headerField);
373526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
374526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + "is not Long-Integer header field!");
375526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
376526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
377526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
378526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
379526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
380526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /* Text-String */
381526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.TRANSACTION_ID:
382526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.REPLY_CHARGING_ID:
383526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.AUX_APPLIC_ID:
384526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.APPLIC_ID:
385526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.REPLY_APPLIC_ID:
386526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /**
387526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * The next three header fields are email addresses
388526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * as defined in RFC2822,
389526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * not including the characters "<" and ">"
390526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     */
391526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.MESSAGE_ID:
392526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.REPLACE_ID:
393526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.CANCEL_ID:
394526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /**
395526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * The following field has a different value when
396526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * used in the M-Mbox-Delete.conf and M-Delete.conf PDU.
397526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * For now we ignore this fact, since we do not support these PDUs
398526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     */
399526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.CONTENT_LOCATION:
400526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                {
401526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    byte[] value = parseWapString(pduDataStream, TYPE_TEXT_STRING);
402526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (null != value) {
403526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        try {
404526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            if (LOCAL_LOGV) {
405526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                Log.v(LOG_TAG, "parseHeaders: string: " + headerField + " value: " +
406526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        new String(value));
407526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
408526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            headers.setTextString(value, headerField);
409526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(NullPointerException e) {
410526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log("null pointer error!");
411526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(RuntimeException e) {
412526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log(headerField + "is not Text-String header field!");
413526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            return null;
414526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
415526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
416526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
417526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
418526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
419526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /* Encoded-string-value */
420526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.SUBJECT:
421526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.RECOMMENDED_RETRIEVAL_MODE_TEXT:
422526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.RETRIEVE_TEXT:
423526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.STATUS_TEXT:
424526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.STORE_STATUS_TEXT:
425526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* the next one is not support
426526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * M-Mbox-Delete.conf and M-Delete.conf now */
427526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.RESPONSE_TEXT:
428526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                {
429526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    EncodedStringValue value =
430526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        parseEncodedStringValue(pduDataStream);
431526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (null != value) {
432526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        try {
433526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            if (LOCAL_LOGV) {
434526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                Log.v(LOG_TAG, "parseHeaders: encoded string: " + headerField
435526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        + " value: " + value.getString());
436526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
437526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            headers.setEncodedStringValue(value, headerField);
438526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(NullPointerException e) {
439526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log("null pointer error!");
440526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch (RuntimeException e) {
441526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log(headerField + "is not Encoded-String-Value header field!");
442526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            return null;
443526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
444526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
445526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
446526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
447526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
448526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /* Addressing model */
449526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.BCC:
450526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.CC:
451526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.TO:
452526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                {
453526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    EncodedStringValue value =
454526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        parseEncodedStringValue(pduDataStream);
455526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (null != value) {
456526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        byte[] address = value.getTextString();
457526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (null != address) {
458526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            String str = new String(address);
459526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            if (LOCAL_LOGV) {
460526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                Log.v(LOG_TAG, "parseHeaders: (to/cc/bcc) address: " + headerField
461526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        + " value: " + str);
462526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
463526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            int endIndex = str.indexOf("/");
464526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            if (endIndex > 0) {
465526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                str = str.substring(0, endIndex);
466526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
467526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            try {
468526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                value.setTextString(str.getBytes());
469526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            } catch(NullPointerException e) {
470526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                log("null pointer error!");
471526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                return null;
472526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
473526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
474526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
475526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        try {
476526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            headers.appendEncodedStringValue(value, headerField);
477526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(NullPointerException e) {
478526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log("null pointer error!");
479526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(RuntimeException e) {
480526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log(headerField + "is not Encoded-String-Value header field!");
481526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            return null;
482526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
483526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
484526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
485526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
486526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
487526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /* Value-length
488526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * (Absolute-token Date-value | Relative-token Delta-seconds-value) */
489526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.DELIVERY_TIME:
490526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.EXPIRY:
491526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.REPLY_CHARGING_DEADLINE:
492526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                {
493526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* parse Value-length */
494526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    parseValueLength(pduDataStream);
495526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
496526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Absolute-token or Relative-token */
497526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    int token = extractByteValue(pduDataStream);
498526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
499526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Date-value or Delta-seconds-value */
500526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    long timeValue;
501526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
502526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        timeValue = parseLongInteger(pduDataStream);
503526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
504526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + "is not Long-Integer header field!");
505526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
506526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
507526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (PduHeaders.VALUE_RELATIVE_TOKEN == token) {
508526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        /* need to convert the Delta-seconds-value
509526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * into Date-value */
510526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        timeValue = System.currentTimeMillis()/1000 + timeValue;
511526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
512526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
513526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
514526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (LOCAL_LOGV) {
515526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            Log.v(LOG_TAG, "parseHeaders: time value: " + headerField
516526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    + " value: " + timeValue);
517526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
518526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        headers.setLongInteger(timeValue, headerField);
519526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
520526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + "is not Long-Integer header field!");
521526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
522526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
523526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
524526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
525526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
526526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.FROM: {
527526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* From-value =
528526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * Value-length
529526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * (Address-present-token Encoded-string-value | Insert-address-token)
530526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     */
531526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    EncodedStringValue from = null;
532526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    parseValueLength(pduDataStream); /* parse value-length */
533526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
534526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Address-present-token or Insert-address-token */
535526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    int fromToken = extractByteValue(pduDataStream);
536526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
537526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Address-present-token or Insert-address-token */
538526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (PduHeaders.FROM_ADDRESS_PRESENT_TOKEN == fromToken) {
539526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        /* Encoded-string-value */
540526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        from = parseEncodedStringValue(pduDataStream);
541526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (null != from) {
542526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            byte[] address = from.getTextString();
543526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            if (null != address) {
544526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                String str = new String(address);
545526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                int endIndex = str.indexOf("/");
546526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                if (endIndex > 0) {
547526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    str = str.substring(0, endIndex);
548526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                }
549526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                try {
550526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    from.setTextString(str.getBytes());
551526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                } catch(NullPointerException e) {
552526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    log("null pointer error!");
553526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    return null;
554526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                }
555526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
556526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
557526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } else {
558526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        try {
559526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            from = new EncodedStringValue(
560526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes());
561526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(NullPointerException e) {
562526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log(headerField + "is not Encoded-String-Value header field!");
563526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            return null;
564526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
565526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
566526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
567526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
568526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (LOCAL_LOGV) {
569526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            Log.v(LOG_TAG, "parseHeaders: from address: " + headerField
570526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    + " value: " + from.getString());
571526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
572526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        headers.setEncodedStringValue(from, PduHeaders.FROM);
573526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(NullPointerException e) {
574526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log("null pointer error!");
575526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
576526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + "is not Encoded-String-Value header field!");
577526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
578526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
579526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
580526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
581526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
582526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.MESSAGE_CLASS: {
583526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Message-class-value = Class-identifier | Token-text */
584526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    pduDataStream.mark(1);
585526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    int messageClass = extractByteValue(pduDataStream);
586526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (LOCAL_LOGV) {
587526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.v(LOG_TAG, "parseHeaders: MESSAGE_CLASS: " + headerField
588526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                + " value: " + messageClass);
589526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
590526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
591526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (messageClass >= PduHeaders.MESSAGE_CLASS_PERSONAL) {
592526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        /* Class-identifier */
593526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        try {
594526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            if (PduHeaders.MESSAGE_CLASS_PERSONAL == messageClass) {
595526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                headers.setTextString(
596526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes(),
597526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        PduHeaders.MESSAGE_CLASS);
598526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            } else if (PduHeaders.MESSAGE_CLASS_ADVERTISEMENT == messageClass) {
599526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                headers.setTextString(
600526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes(),
601526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        PduHeaders.MESSAGE_CLASS);
602526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            } else if (PduHeaders.MESSAGE_CLASS_INFORMATIONAL == messageClass) {
603526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                headers.setTextString(
604526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes(),
605526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        PduHeaders.MESSAGE_CLASS);
606526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            } else if (PduHeaders.MESSAGE_CLASS_AUTO == messageClass) {
607526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                headers.setTextString(
608526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes(),
609526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        PduHeaders.MESSAGE_CLASS);
610526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
611526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(NullPointerException e) {
612526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log("null pointer error!");
613526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(RuntimeException e) {
614526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log(headerField + "is not Text-String header field!");
615526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            return null;
616526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
617526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } else {
618526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        /* Token-text */
619526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        pduDataStream.reset();
620526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        byte[] messageClassString = parseWapString(pduDataStream, TYPE_TEXT_STRING);
621526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (null != messageClassString) {
622526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            try {
623526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                headers.setTextString(messageClassString, PduHeaders.MESSAGE_CLASS);
624526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            } catch(NullPointerException e) {
625526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                log("null pointer error!");
626526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            } catch(RuntimeException e) {
627526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                log(headerField + "is not Text-String header field!");
628526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                return null;
629526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
630526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
631526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
632526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
633526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
634526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
635526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.MMS_VERSION: {
636526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    int version = parseShortInteger(pduDataStream);
637526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
638526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
639526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (LOCAL_LOGV) {
640526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            Log.v(LOG_TAG, "parseHeaders: MMS_VERSION: " + headerField
641526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    + " value: " + version);
642526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
643526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        headers.setOctet(version, PduHeaders.MMS_VERSION);
644526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(InvalidHeaderValueException e) {
645526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log("Set invalid Octet value: " + version +
646526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                " into the header filed: " + headerField);
647526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
648526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
649526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + "is not Octet header field!");
650526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
651526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
652526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
653526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
654526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
655526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.PREVIOUSLY_SENT_BY: {
656526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Previously-sent-by-value =
657526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * Value-length Forwarded-count-value Encoded-string-value */
658526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* parse value-length */
659526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    parseValueLength(pduDataStream);
660526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
661526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* parse Forwarded-count-value */
662526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
663526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        parseIntegerValue(pduDataStream);
664526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
665526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + " is not Integer-Value");
666526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
667526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
668526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
669526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* parse Encoded-string-value */
670526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    EncodedStringValue previouslySentBy =
671526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        parseEncodedStringValue(pduDataStream);
672526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (null != previouslySentBy) {
673526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        try {
674526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            if (LOCAL_LOGV) {
675526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                Log.v(LOG_TAG, "parseHeaders: PREVIOUSLY_SENT_BY: " + headerField
676526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        + " value: " + previouslySentBy.getString());
677526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
678526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            headers.setEncodedStringValue(previouslySentBy,
679526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    PduHeaders.PREVIOUSLY_SENT_BY);
680526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(NullPointerException e) {
681526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log("null pointer error!");
682526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(RuntimeException e) {
683526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log(headerField + "is not Encoded-String-Value header field!");
684526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            return null;
685526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
686526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
687526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
688526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
689526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
690526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.PREVIOUSLY_SENT_DATE: {
691526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Previously-sent-date-value =
692526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * Value-length Forwarded-count-value Date-value */
693526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* parse value-length */
694526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    parseValueLength(pduDataStream);
695526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
696526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* parse Forwarded-count-value */
697526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
698526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        parseIntegerValue(pduDataStream);
699526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
700526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + " is not Integer-Value");
701526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
702526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
703526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
704526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Date-value */
705526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
706526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        long perviouslySentDate = parseLongInteger(pduDataStream);
707526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (LOCAL_LOGV) {
708526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            Log.v(LOG_TAG, "parseHeaders: PREVIOUSLY_SENT_DATE: " + headerField
709526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    + " value: " + perviouslySentDate);
710526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
711526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        headers.setLongInteger(perviouslySentDate,
712526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                PduHeaders.PREVIOUSLY_SENT_DATE);
713526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
714526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + "is not Long-Integer header field!");
715526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
716526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
717526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
718526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
719526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
720526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.MM_FLAGS: {
721526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* MM-flags-value =
722526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * Value-length
723526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * ( Add-token | Remove-token | Filter-token )
724526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * Encoded-string-value
725526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     */
726526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (LOCAL_LOGV) {
727526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.v(LOG_TAG, "parseHeaders: MM_FLAGS: " + headerField
728526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                + " NOT REALLY SUPPORTED");
729526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
730526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
731526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* parse Value-length */
732526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    parseValueLength(pduDataStream);
733526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
734526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Add-token | Remove-token | Filter-token */
735526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    extractByteValue(pduDataStream);
736526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
737526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Encoded-string-value */
738526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    parseEncodedStringValue(pduDataStream);
739526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
740526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* not store this header filed in "headers",
741526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * because now PduHeaders doesn't support it */
742526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
743526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
744526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
745526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /* Value-length
746526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * (Message-total-token | Size-total-token) Integer-Value */
747526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.MBOX_TOTALS:
748526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.MBOX_QUOTAS:
749526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                {
750526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (LOCAL_LOGV) {
751526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.v(LOG_TAG, "parseHeaders: MBOX_TOTALS: " + headerField);
752526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
753526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Value-length */
754526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    parseValueLength(pduDataStream);
755526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
756526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* Message-total-token | Size-total-token */
757526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    extractByteValue(pduDataStream);
758526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
759526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /*Integer-Value*/
760526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    try {
761526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        parseIntegerValue(pduDataStream);
762526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } catch(RuntimeException e) {
763526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log(headerField + " is not Integer-Value");
764526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
765526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
766526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
767526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* not store these headers filed in "headers",
768526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    because now PduHeaders doesn't support them */
769526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
770526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
771526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
772526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.ELEMENT_DESCRIPTOR: {
773526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (LOCAL_LOGV) {
774526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.v(LOG_TAG, "parseHeaders: ELEMENT_DESCRIPTOR: " + headerField);
775526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
776526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    parseContentType(pduDataStream, null);
777526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
778526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* not store this header filed in "headers",
779526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    because now PduHeaders doesn't support it */
780526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
781526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
782526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
783526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.CONTENT_TYPE: {
784526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    HashMap<Integer, Object> map =
785526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        new HashMap<Integer, Object>();
786526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    byte[] contentType =
787526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        parseContentType(pduDataStream, map);
788526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
789526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (null != contentType) {
790526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        try {
791526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            if (LOCAL_LOGV) {
792526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                Log.v(LOG_TAG, "parseHeaders: CONTENT_TYPE: " + headerField +
793526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        contentType.toString());
794526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
795526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            headers.setTextString(contentType, PduHeaders.CONTENT_TYPE);
796526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(NullPointerException e) {
797526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log("null pointer error!");
798526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch(RuntimeException e) {
799526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            log(headerField + "is not Text-String header field!");
800526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            return null;
801526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
802526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
803526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
804526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* get start parameter */
805526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    mStartParam = (byte[]) map.get(PduPart.P_START);
806526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
807526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /* get charset parameter */
808526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    mTypeParam= (byte[]) map.get(PduPart.P_TYPE);
809526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
810526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    keepParsing = false;
811526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
812526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
813526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
814526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.CONTENT:
815526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.ADDITIONAL_HEADERS:
816526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduHeaders.ATTRIBUTES:
817526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                default: {
818526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (LOCAL_LOGV) {
819526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.v(LOG_TAG, "parseHeaders: Unknown header: " + headerField);
820526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
821526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    log("Unknown header");
822526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
823526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
824526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
825526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
826526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return headers;
827526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
828526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
829526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
830526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse pdu parts.
831526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
832526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
833526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return parts in PduBody structure
834526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
835032e0398ba2770edd52c543482afbae6f92ff29bYe Wen    protected PduBody parseParts(ByteArrayInputStream pduDataStream) {
836526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (pduDataStream == null) {
837526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return null;
838526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
839526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
840526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int count = parseUnsignedInt(pduDataStream); // get the number of parts
841526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        PduBody body = new PduBody();
842526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
843526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        for (int i = 0 ; i < count ; i++) {
844526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int headerLength = parseUnsignedInt(pduDataStream);
845526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int dataLength = parseUnsignedInt(pduDataStream);
846526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            PduPart part = new PduPart();
847526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int startPos = pduDataStream.available();
848526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (startPos <= 0) {
849526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Invalid part.
850526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return null;
851526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
852526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
853526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            /* parse part's content-type */
854526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            HashMap<Integer, Object> map = new HashMap<Integer, Object>();
855526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            byte[] contentType = parseContentType(pduDataStream, map);
856526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (null != contentType) {
857526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                part.setContentType(contentType);
858526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } else {
859526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                part.setContentType((PduContentTypes.contentTypes[0]).getBytes()); //"*/*"
860526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
861526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
862526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            /* get name parameter */
863526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            byte[] name = (byte[]) map.get(PduPart.P_NAME);
864526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (null != name) {
865526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                part.setName(name);
866526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
867526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
868526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            /* get charset parameter */
869526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            Integer charset = (Integer) map.get(PduPart.P_CHARSET);
870526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (null != charset) {
871526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                part.setCharset(charset);
872526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
873526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
874526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            /* parse part's headers */
875526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int endPos = pduDataStream.available();
876526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int partHeaderLen = headerLength - (startPos - endPos);
877526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (partHeaderLen > 0) {
878526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (false == parsePartHeaders(pduDataStream, part, partHeaderLen)) {
879526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    // Parse part header faild.
880526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return null;
881526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
882526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } else if (partHeaderLen < 0) {
883526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Invalid length of content-type.
884526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return null;
885526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
886526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
887526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            /* FIXME: check content-id, name, filename and content location,
888526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen             * if not set anyone of them, generate a default content-location
889526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen             */
890526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if ((null == part.getContentLocation())
891526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    && (null == part.getName())
892526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    && (null == part.getFilename())
893526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    && (null == part.getContentId())) {
894526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                part.setContentLocation(Long.toOctalString(
895526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        System.currentTimeMillis()).getBytes());
896526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
897526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
898526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            /* get part's data */
899526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (dataLength > 0) {
900526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] partData = new byte[dataLength];
901526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                String partContentType = new String(part.getContentType());
902526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                pduDataStream.read(partData, 0, dataLength);
903526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (partContentType.equalsIgnoreCase(ContentType.MULTIPART_ALTERNATIVE)) {
904526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    // parse "multipart/vnd.wap.multipart.alternative".
905526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    PduBody childBody = parseParts(new ByteArrayInputStream(partData));
906526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    // take the first part of children.
907526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    part = childBody.getPart(0);
908526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                } else {
909526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    // Check Content-Transfer-Encoding.
910526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    byte[] partDataEncoding = part.getContentTransferEncoding();
911526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (null != partDataEncoding) {
912526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        String encoding = new String(partDataEncoding);
913526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) {
914526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            // Decode "base64" into "binary".
915526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            partData = Base64.decodeBase64(partData);
916526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) {
917526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            // Decode "quoted-printable" into "binary".
918526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            partData = QuotedPrintable.decodeQuotedPrintable(partData);
919526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } else {
920526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            // "binary" is the default encoding.
921526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
922526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
923526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (null == partData) {
924526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        log("Decode part data error!");
925526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return null;
926526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
927526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    part.setData(partData);
928526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
929526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
930526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
931526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            /* add this part to body */
932526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (THE_FIRST_PART == checkPartPosition(part)) {
933526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /* this is the first part */
934526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                body.addPart(0, part);
935526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } else {
936526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /* add the part to the end */
937526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                body.addPart(part);
938526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
939526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
940526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
941526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return body;
942526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
943526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
944526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
945526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Log status.
946526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
947526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param text log information
948526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
949526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static void log(String text) {
950526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (LOCAL_LOGV) {
951526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            Log.v(LOG_TAG, text);
952526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
953526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
954526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
955526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
956526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse unsigned integer.
957526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
958526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
959526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return the integer, -1 when failed
960526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
961526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static int parseUnsignedInt(ByteArrayInputStream pduDataStream) {
962526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
963526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * From wap-230-wsp-20010705-a.pdf
964526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * The maximum size of a uintvar is 32 bits.
965526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * So it will be encoded in no more than 5 octets.
966526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
967526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
968526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int result = 0;
969526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int temp = pduDataStream.read();
970526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (temp == -1) {
971526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return temp;
972526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
973526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
974526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        while((temp & 0x80) != 0) {
975526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            result = result << 7;
976526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            result |= temp & 0x7F;
977526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            temp = pduDataStream.read();
978526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (temp == -1) {
979526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return temp;
980526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
981526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
982526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
983526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        result = result << 7;
984526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        result |= temp & 0x7F;
985526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
986526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return result;
987526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
988526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
989526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
990526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse value length.
991526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
992526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
993526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return the integer
994526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
995526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static int parseValueLength(ByteArrayInputStream pduDataStream) {
996526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
997526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * From wap-230-wsp-20010705-a.pdf
998526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Value-length = Short-length | (Length-quote Length)
999526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Short-length = <Any octet 0-30>
1000526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Length-quote = <Octet 31>
1001526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Length = Uintvar-integer
1002526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Uintvar-integer = 1*5 OCTET
1003526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1004526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1005526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int temp = pduDataStream.read();
1006526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(-1 != temp);
1007526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int first = temp & 0xFF;
1008526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1009526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (first <= SHORT_LENGTH_MAX) {
1010526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return first;
1011526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        } else if (first == LENGTH_QUOTE) {
1012526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return parseUnsignedInt(pduDataStream);
1013526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1014526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1015526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        throw new RuntimeException ("Value length > LENGTH_QUOTE!");
1016526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1017526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1018526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1019526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse encoded string value.
1020526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1021526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
1022526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return the EncodedStringValue
1023526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1024526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static EncodedStringValue parseEncodedStringValue(ByteArrayInputStream pduDataStream){
1025526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
1026526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * From OMA-TS-MMS-ENC-V1_3-20050927-C.pdf
1027526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Encoded-string-value = Text-string | Value-length Char-set Text-string
1028526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1029526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1030526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        pduDataStream.mark(1);
1031526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        EncodedStringValue returnValue = null;
1032526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int charset = 0;
1033526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int temp = pduDataStream.read();
1034526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(-1 != temp);
1035526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int first = temp & 0xFF;
1036526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (first == 0) {
1037526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return new EncodedStringValue("");
1038526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1039526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1040526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        pduDataStream.reset();
1041526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (first < TEXT_MIN) {
1042526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            parseValueLength(pduDataStream);
1043526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1044526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            charset = parseShortInteger(pduDataStream); //get the "Charset"
1045526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1046526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1047526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        byte[] textString = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1048526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1049526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        try {
1050526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (0 != charset) {
1051526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                returnValue = new EncodedStringValue(charset, textString);
1052526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } else {
1053526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                returnValue = new EncodedStringValue(textString);
1054526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
1055526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        } catch(Exception e) {
1056526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return null;
1057526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1058526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1059526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return returnValue;
1060526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1061526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1062526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1063526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse Text-String or Quoted-String.
1064526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1065526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
1066526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param stringType TYPE_TEXT_STRING or TYPE_QUOTED_STRING
1067526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return the string without End-of-string in byte array
1068526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1069526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static byte[] parseWapString(ByteArrayInputStream pduDataStream,
1070526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int stringType) {
1071526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1072526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
1073526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * From wap-230-wsp-20010705-a.pdf
1074526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Text-string = [Quote] *TEXT End-of-string
1075526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * If the first character in the TEXT is in the range of 128-255,
1076526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * a Quote character must precede it.
1077526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Otherwise the Quote character must be omitted.
1078526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * The Quote is not part of the contents.
1079526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Quote = <Octet 127>
1080526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * End-of-string = <Octet 0>
1081526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         *
1082526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Quoted-string = <Octet 34> *TEXT End-of-string
1083526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         *
1084526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Token-text = Token End-of-string
1085526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1086526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1087526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        // Mark supposed beginning of Text-string
1088526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        // We will have to mark again if first char is QUOTE or QUOTED_STRING_FLAG
1089526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        pduDataStream.mark(1);
1090526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1091526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        // Check first char
1092526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int temp = pduDataStream.read();
1093526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(-1 != temp);
1094526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if ((TYPE_QUOTED_STRING == stringType) &&
1095526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                (QUOTED_STRING_FLAG == temp)) {
1096526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            // Mark again if QUOTED_STRING_FLAG and ignore it
1097526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            pduDataStream.mark(1);
1098526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        } else if ((TYPE_TEXT_STRING == stringType) &&
1099526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                (QUOTE == temp)) {
1100526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            // Mark again if QUOTE and ignore it
1101526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            pduDataStream.mark(1);
1102526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        } else {
1103526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            // Otherwise go back to origin
1104526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            pduDataStream.reset();
1105526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1106526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1107526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        // We are now definitely at the beginning of string
1108526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
1109526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Return *TOKEN or *TEXT (Text-String without QUOTE,
1110526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Quoted-String without QUOTED_STRING_FLAG and without End-of-string)
1111526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1112526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return getWapString(pduDataStream, stringType);
1113526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1114526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1115526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1116526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Check TOKEN data defined in RFC2616.
1117526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param ch checking data
1118526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return true when ch is TOKEN, false when ch is not TOKEN
1119526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1120526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static boolean isTokenCharacter(int ch) {
1121526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
1122526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Token      = 1*<any CHAR except CTLs or separators>
1123526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * separators = "("(40) | ")"(41) | "<"(60) | ">"(62) | "@"(64)
1124526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         *            | ","(44) | ";"(59) | ":"(58) | "\"(92) | <">(34)
1125526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         *            | "/"(47) | "["(91) | "]"(93) | "?"(63) | "="(61)
1126526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         *            | "{"(123) | "}"(125) | SP(32) | HT(9)
1127526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * CHAR       = <any US-ASCII character (octets 0 - 127)>
1128526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * CTL        = <any US-ASCII control character
1129526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         *            (octets 0 - 31) and DEL (127)>
1130526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * SP         = <US-ASCII SP, space (32)>
1131526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * HT         = <US-ASCII HT, horizontal-tab (9)>
1132526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1133526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if((ch < 33) || (ch > 126)) {
1134526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return false;
1135526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1136526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1137526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        switch(ch) {
1138526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '"': /* '"' */
1139526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '(': /* '(' */
1140526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case ')': /* ')' */
1141526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case ',': /* ',' */
1142526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '/': /* '/' */
1143526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case ':': /* ':' */
1144526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case ';': /* ';' */
1145526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '<': /* '<' */
1146526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '=': /* '=' */
1147526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '>': /* '>' */
1148526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '?': /* '?' */
1149526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '@': /* '@' */
1150526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '[': /* '[' */
1151526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '\\': /* '\' */
1152526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case ']': /* ']' */
1153526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '{': /* '{' */
1154526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '}': /* '}' */
1155526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return false;
1156526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1157526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1158526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return true;
1159526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1160526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1161526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1162526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Check TEXT data defined in RFC2616.
1163526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param ch checking data
1164526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return true when ch is TEXT, false when ch is not TEXT
1165526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1166526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static boolean isText(int ch) {
1167526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
1168526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * TEXT = <any OCTET except CTLs,
1169526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         *      but including LWS>
1170526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * CTL  = <any US-ASCII control character
1171526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         *      (octets 0 - 31) and DEL (127)>
1172526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * LWS  = [CRLF] 1*( SP | HT )
1173526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * CRLF = CR LF
1174526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * CR   = <US-ASCII CR, carriage return (13)>
1175526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * LF   = <US-ASCII LF, linefeed (10)>
1176526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1177526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if(((ch >= 32) && (ch <= 126)) || ((ch >= 128) && (ch <= 255))) {
1178526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return true;
1179526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1180526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1181526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        switch(ch) {
1182526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '\t': /* '\t' */
1183526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '\n': /* '\n' */
1184526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case '\r': /* '\r' */
1185526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return true;
1186526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1187526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1188526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return false;
1189526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1190526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1191526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static byte[] getWapString(ByteArrayInputStream pduDataStream,
1192526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int stringType) {
1193526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1194526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        ByteArrayOutputStream out = new ByteArrayOutputStream();
1195526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int temp = pduDataStream.read();
1196526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(-1 != temp);
1197526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        while((-1 != temp) && ('\0' != temp)) {
1198526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            // check each of the character
1199526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (stringType == TYPE_TOKEN_STRING) {
1200526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (isTokenCharacter(temp)) {
1201526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    out.write(temp);
1202526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1203526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } else {
1204526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (isText(temp)) {
1205526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    out.write(temp);
1206526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1207526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
1208526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1209526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            temp = pduDataStream.read();
1210526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            assert(-1 != temp);
1211526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1212526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1213526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (out.size() > 0) {
1214526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return out.toByteArray();
1215526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1216526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1217526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return null;
1218526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1219526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1220526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1221526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Extract a byte value from the input stream.
1222526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1223526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
1224526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return the byte
1225526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1226526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static int extractByteValue(ByteArrayInputStream pduDataStream) {
1227526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1228526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int temp = pduDataStream.read();
1229526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(-1 != temp);
1230526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return temp & 0xFF;
1231526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1232526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1233526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1234526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse Short-Integer.
1235526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1236526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
1237526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return the byte
1238526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1239526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static int parseShortInteger(ByteArrayInputStream pduDataStream) {
1240526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
1241526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * From wap-230-wsp-20010705-a.pdf
1242526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Short-integer = OCTET
1243526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Integers in range 0-127 shall be encoded as a one
1244526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * octet value with the most significant bit set to one (1xxx xxxx)
1245526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * and with the value in the remaining least significant bits.
1246526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1247526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1248526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int temp = pduDataStream.read();
1249526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(-1 != temp);
1250526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return temp & 0x7F;
1251526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1252526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1253526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1254526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse Long-Integer.
1255526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1256526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
1257526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return long integer
1258526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1259526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static long parseLongInteger(ByteArrayInputStream pduDataStream) {
1260526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
1261526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * From wap-230-wsp-20010705-a.pdf
1262526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Long-integer = Short-length Multi-octet-integer
1263526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * The Short-length indicates the length of the Multi-octet-integer
1264526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Multi-octet-integer = 1*30 OCTET
1265526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * The content octets shall be an unsigned integer value
1266526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * with the most significant octet encoded first (big-endian representation).
1267526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * The minimum number of octets must be used to encode the value.
1268526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Short-length = <Any octet 0-30>
1269526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1270526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1271526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int temp = pduDataStream.read();
1272526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(-1 != temp);
1273526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int count = temp & 0xFF;
1274526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1275526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (count > LONG_INTEGER_LENGTH_MAX) {
1276526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            throw new RuntimeException("Octet count greater than 8 and I can't represent that!");
1277526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1278526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1279526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        long result = 0;
1280526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1281526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        for (int i = 0 ; i < count ; i++) {
1282526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            temp = pduDataStream.read();
1283526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            assert(-1 != temp);
1284526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            result <<= 8;
1285526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            result += (temp & 0xFF);
1286526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1287526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1288526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return result;
1289526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1290526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1291526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1292526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse Integer-Value.
1293526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1294526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
1295526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return long integer
1296526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1297526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static long parseIntegerValue(ByteArrayInputStream pduDataStream) {
1298526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
1299526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * From wap-230-wsp-20010705-a.pdf
1300526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Integer-Value = Short-integer | Long-integer
1301526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1302526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1303526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        pduDataStream.mark(1);
1304526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int temp = pduDataStream.read();
1305526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(-1 != temp);
1306526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        pduDataStream.reset();
1307526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (temp > SHORT_INTEGER_MAX) {
1308526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return parseShortInteger(pduDataStream);
1309526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        } else {
1310526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return parseLongInteger(pduDataStream);
1311526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1312526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1313526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1314526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1315526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * To skip length of the wap value.
1316526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1317526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
1318526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param length area size
1319526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return the values in this area
1320526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1321526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static int skipWapValue(ByteArrayInputStream pduDataStream, int length) {
1322526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1323526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        byte[] area = new byte[length];
1324526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int readLen = pduDataStream.read(area, 0, length);
1325526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (readLen < length) { //The actually read length is lower than the length
1326526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return -1;
1327526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        } else {
1328526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return readLen;
1329526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1330526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1331526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1332526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1333526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse content type parameters. For now we just support
1334526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * four parameters used in mms: "type", "start", "name", "charset".
1335526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1336526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
1337526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param map to store parameters of Content-Type field
1338526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param length length of all the parameters
1339526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1340526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static void parseContentTypeParams(ByteArrayInputStream pduDataStream,
1341526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            HashMap<Integer, Object> map, Integer length) {
1342526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
1343526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * From wap-230-wsp-20010705-a.pdf
1344526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Parameter = Typed-parameter | Untyped-parameter
1345526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Typed-parameter = Well-known-parameter-token Typed-value
1346526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * the actual expected type of the value is implied by the well-known parameter
1347526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Well-known-parameter-token = Integer-value
1348526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * the code values used for parameters are specified in the Assigned Numbers appendix
1349526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Typed-value = Compact-value | Text-value
1350526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * In addition to the expected type, there may be no value.
1351526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * If the value cannot be encoded using the expected type, it shall be encoded as text.
1352526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Compact-value = Integer-value |
1353526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Date-value | Delta-seconds-value | Q-value | Version-value |
1354526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Uri-value
1355526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Untyped-parameter = Token-text Untyped-value
1356526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * the type of the value is unknown, but it shall be encoded as an integer,
1357526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * if that is possible.
1358526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Untyped-value = Integer-value | Text-value
1359526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1360526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1361526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(length > 0);
1362526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1363526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int startPos = pduDataStream.available();
1364526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int tempPos = 0;
1365526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int lastLen = length;
1366526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        while(0 < lastLen) {
1367526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int param = pduDataStream.read();
1368526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            assert(-1 != param);
1369526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            lastLen--;
1370526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1371526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            switch (param) {
1372526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                /**
1373526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * From rfc2387, chapter 3.1
1374526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * The type parameter must be specified and its value is the MIME media
1375526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * type of the "root" body part. It permits a MIME user agent to
1376526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * determine the content-type without reference to the enclosed body
1377526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * part. If the value of the type parameter and the root body part's
1378526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * content-type differ then the User Agent's behavior is undefined.
1379526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 *
1380526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * From wap-230-wsp-20010705-a.pdf
1381526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * type = Constrained-encoding
1382526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * Constrained-encoding = Extension-Media | Short-integer
1383526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 * Extension-media = *TEXT End-of-string
1384526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                 */
1385526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduPart.P_TYPE:
1386526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduPart.P_CT_MR_TYPE:
1387526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    pduDataStream.mark(1);
1388526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    int first = extractByteValue(pduDataStream);
1389526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    pduDataStream.reset();
1390526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (first > TEXT_MAX) {
1391526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        // Short-integer (well-known type)
1392526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        int index = parseShortInteger(pduDataStream);
1393526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1394526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (index < PduContentTypes.contentTypes.length) {
1395526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            byte[] type = (PduContentTypes.contentTypes[index]).getBytes();
1396526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            map.put(PduPart.P_TYPE, type);
1397526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } else {
1398526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            //not support this type, ignore it.
1399526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
1400526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } else {
1401526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        // Text-String (extension-media)
1402526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        byte[] type = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1403526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if ((null != type) && (null != map)) {
1404526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            map.put(PduPart.P_TYPE, type);
1405526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
1406526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
1407526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1408526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    tempPos = pduDataStream.available();
1409526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    lastLen = length - (startPos - tempPos);
1410526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
1411526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1412526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /**
1413526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2.3.
1414526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * Start Parameter Referring to Presentation
1415526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     *
1416526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * From rfc2387, chapter 3.2
1417526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * The start parameter, if given, is the content-ID of the compound
1418526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * object's "root". If not present the "root" is the first body part in
1419526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * the Multipart/Related entity. The "root" is the element the
1420526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * applications processes first.
1421526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     *
1422526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * From wap-230-wsp-20010705-a.pdf
1423526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * start = Text-String
1424526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     */
1425526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduPart.P_START:
1426526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduPart.P_DEP_START:
1427526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    byte[] start = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1428526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if ((null != start) && (null != map)) {
1429526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        map.put(PduPart.P_START, start);
1430526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
1431526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1432526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    tempPos = pduDataStream.available();
1433526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    lastLen = length - (startPos - tempPos);
1434526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
1435526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1436526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /**
1437526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * From oma-ts-mms-conf-v1_3.pdf
1438526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * In creation, the character set SHALL be either us-ascii
1439526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * (IANA MIBenum 3) or utf-8 (IANA MIBenum 106)[Unicode].
1440526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * In retrieval, both us-ascii and utf-8 SHALL be supported.
1441526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     *
1442526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * From wap-230-wsp-20010705-a.pdf
1443526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * charset = Well-known-charset|Text-String
1444526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * Well-known-charset = Any-charset | Integer-value
1445526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * Both are encoded using values from Character Set
1446526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * Assignments table in Assigned Numbers
1447526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * Any-charset = <Octet 128>
1448526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * Equivalent to the special RFC2616 charset value "*"
1449526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     */
1450526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduPart.P_CHARSET:
1451526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    pduDataStream.mark(1);
1452526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    int firstValue = extractByteValue(pduDataStream);
1453526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    pduDataStream.reset();
1454526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    //Check first char
1455526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (((firstValue > TEXT_MIN) && (firstValue < TEXT_MAX)) ||
1456526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            (END_STRING_FLAG == firstValue)) {
1457526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        //Text-String (extension-charset)
1458526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        byte[] charsetStr = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1459526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        try {
1460526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            int charsetInt = CharacterSets.getMibEnumValue(
1461526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    new String(charsetStr));
1462526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            map.put(PduPart.P_CHARSET, charsetInt);
1463526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        } catch (UnsupportedEncodingException e) {
1464526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            // Not a well-known charset, use "*".
1465526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            Log.e(LOG_TAG, Arrays.toString(charsetStr), e);
1466526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            map.put(PduPart.P_CHARSET, CharacterSets.ANY_CHARSET);
1467526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
1468526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    } else {
1469526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        //Well-known-charset
1470526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        int charset = (int) parseIntegerValue(pduDataStream);
1471526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (map != null) {
1472526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            map.put(PduPart.P_CHARSET, charset);
1473526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
1474526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
1475526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1476526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    tempPos = pduDataStream.available();
1477526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    lastLen = length - (startPos - tempPos);
1478526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
1479526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1480526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    /**
1481526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * From oma-ts-mms-conf-v1_3.pdf
1482526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * A name for multipart object SHALL be encoded using name-parameter
1483526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * for Content-Type header in WSP multipart headers.
1484526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     *
1485526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * From wap-230-wsp-20010705-a.pdf
1486526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     * name = Text-String
1487526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                     */
1488526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduPart.P_DEP_NAME:
1489526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                case PduPart.P_NAME:
1490526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    byte[] name = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1491526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if ((null != name) && (null != map)) {
1492526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        map.put(PduPart.P_NAME, name);
1493526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
1494526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1495526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    tempPos = pduDataStream.available();
1496526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    lastLen = length - (startPos - tempPos);
1497526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
1498526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                default:
1499526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (LOCAL_LOGV) {
1500526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.v(LOG_TAG, "Not supported Content-Type parameter");
1501526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
1502526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (-1 == skipWapValue(pduDataStream, lastLen)) {
1503526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.e(LOG_TAG, "Corrupt Content-Type");
1504526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                } else {
1505526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    lastLen = 0;
1506526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1507526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                break;
1508526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
1509526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1510526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1511526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (0 != lastLen) {
1512526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            Log.e(LOG_TAG, "Corrupt Content-Type");
1513526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1514526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1515526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1516526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1517526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse content type.
1518526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1519526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
1520526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param map to store parameters in Content-Type header field
1521526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return Content-Type value
1522526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1523526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static byte[] parseContentType(ByteArrayInputStream pduDataStream,
1524526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            HashMap<Integer, Object> map) {
1525526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
1526526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * From wap-230-wsp-20010705-a.pdf
1527526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Content-type-value = Constrained-media | Content-general-form
1528526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Content-general-form = Value-length Media-type
1529526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Media-type = (Well-known-media | Extension-Media) *(Parameter)
1530526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1531526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1532526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1533526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        byte[] contentType = null;
1534526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        pduDataStream.mark(1);
1535526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int temp = pduDataStream.read();
1536526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(-1 != temp);
1537526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        pduDataStream.reset();
1538526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1539526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int cur = (temp & 0xFF);
1540526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1541526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (cur < TEXT_MIN) {
1542526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int length = parseValueLength(pduDataStream);
1543526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int startPos = pduDataStream.available();
1544526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            pduDataStream.mark(1);
1545526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            temp = pduDataStream.read();
1546526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            assert(-1 != temp);
1547526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            pduDataStream.reset();
1548526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int first = (temp & 0xFF);
1549526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1550526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if ((first >= TEXT_MIN) && (first <= TEXT_MAX)) {
1551526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1552526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } else if (first > TEXT_MAX) {
1553526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                int index = parseShortInteger(pduDataStream);
1554526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1555526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (index < PduContentTypes.contentTypes.length) { //well-known type
1556526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    contentType = (PduContentTypes.contentTypes[index]).getBytes();
1557526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                } else {
1558526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    pduDataStream.reset();
1559526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1560526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1561526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } else {
1562526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                Log.e(LOG_TAG, "Corrupt content-type");
1563526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*"
1564526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
1565526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1566526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int endPos = pduDataStream.available();
1567526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int parameterLen = length - (startPos - endPos);
1568526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (parameterLen > 0) {//have parameters
1569526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                parseContentTypeParams(pduDataStream, map, parameterLen);
1570526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
1571526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1572526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (parameterLen < 0) {
1573526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                Log.e(LOG_TAG, "Corrupt MMS message");
1574526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return (PduContentTypes.contentTypes[0]).getBytes(); //"*/*"
1575526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
1576526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        } else if (cur <= TEXT_MAX) {
1577526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            contentType = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1578526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        } else {
1579526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            contentType =
1580526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                (PduContentTypes.contentTypes[parseShortInteger(pduDataStream)]).getBytes();
1581526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1582526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1583526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return contentType;
1584526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1585526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1586526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1587526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Parse part's headers.
1588526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1589526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param pduDataStream pdu data input stream
1590526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param part to store the header informations of the part
1591526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param length length of the headers
1592526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return true if parse successfully, false otherwise
1593526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1594032e0398ba2770edd52c543482afbae6f92ff29bYe Wen    protected boolean parsePartHeaders(ByteArrayInputStream pduDataStream,
1595526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            PduPart part, int length) {
1596526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != pduDataStream);
1597526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != part);
1598526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(length > 0);
1599526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1600526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /**
1601526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * From oma-ts-mms-conf-v1_3.pdf, chapter 10.2.
1602526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * A name for multipart object SHALL be encoded using name-parameter
1603526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * for Content-Type header in WSP multipart headers.
1604526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * In decoding, name-parameter of Content-Type SHALL be used if available.
1605526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * If name-parameter of Content-Type is not available,
1606526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * filename parameter of Content-Disposition header SHALL be used if available.
1607526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * If neither name-parameter of Content-Type header nor filename parameter
1608526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * of Content-Disposition header is available,
1609526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Content-Location header SHALL be used if available.
1610526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         *
1611526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * Within SMIL part the reference to the media object parts SHALL use
1612526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * either Content-ID or Content-Location mechanism [RFC2557]
1613526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * and the corresponding WSP part headers in media object parts
1614526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         * contain the corresponding definitions.
1615526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen         */
1616526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int startPos = pduDataStream.available();
1617526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int tempPos = 0;
1618526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int lastLen = length;
1619526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        while(0 < lastLen) {
1620526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            int header = pduDataStream.read();
1621526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            assert(-1 != header);
1622526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            lastLen--;
1623526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1624526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (header > TEXT_MAX) {
1625526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Number assigned headers.
1626526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                switch (header) {
1627526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    case PduPart.P_CONTENT_LOCATION:
1628526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        /**
1629526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
1630526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * Content-location-value = Uri-value
1631526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         */
1632526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        byte[] contentLocation = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1633526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (null != contentLocation) {
1634526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            part.setContentLocation(contentLocation);
1635526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
1636526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1637526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        tempPos = pduDataStream.available();
1638526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        lastLen = length - (startPos - tempPos);
1639526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        break;
1640526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    case PduPart.P_CONTENT_ID:
1641526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        /**
1642526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
1643526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * Content-ID-value = Quoted-string
1644526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         */
1645526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        byte[] contentId = parseWapString(pduDataStream, TYPE_QUOTED_STRING);
1646526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (null != contentId) {
1647526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            part.setContentId(contentId);
1648526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
1649526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1650526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        tempPos = pduDataStream.available();
1651526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        lastLen = length - (startPos - tempPos);
1652526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        break;
1653526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    case PduPart.P_DEP_CONTENT_DISPOSITION:
1654526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    case PduPart.P_CONTENT_DISPOSITION:
1655526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        /**
1656526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * From wap-230-wsp-20010705-a.pdf, chapter 8.4.2.21
1657526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * Content-disposition-value = Value-length Disposition *(Parameter)
1658526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * Disposition = Form-data | Attachment | Inline | Token-text
1659526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * Form-data = <Octet 128>
1660526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * Attachment = <Octet 129>
1661526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * Inline = <Octet 130>
1662526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         */
1663526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1664526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        /*
1665526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * some carrier mmsc servers do not support content_disposition
1666526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         * field correctly
1667526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                         */
1668032e0398ba2770edd52c543482afbae6f92ff29bYe Wen                        if (mParseContentDisposition) {
1669526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            int len = parseValueLength(pduDataStream);
1670526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            pduDataStream.mark(1);
1671526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            int thisStartPos = pduDataStream.available();
1672526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            int thisEndPos = 0;
1673526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            int value = pduDataStream.read();
1674526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1675526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            if (value == PduPart.P_DISPOSITION_FROM_DATA ) {
1676526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA);
1677526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            } else if (value == PduPart.P_DISPOSITION_ATTACHMENT) {
1678526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT);
1679526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            } else if (value == PduPart.P_DISPOSITION_INLINE) {
1680526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                part.setContentDisposition(PduPart.DISPOSITION_INLINE);
1681526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            } else {
1682526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                pduDataStream.reset();
1683526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                /* Token-text */
1684526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                part.setContentDisposition(parseWapString(pduDataStream
1685526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                        , TYPE_TEXT_STRING));
1686526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
1687526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1688526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            /* get filename parameter and skip other parameters */
1689526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            thisEndPos = pduDataStream.available();
1690526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            if (thisStartPos - thisEndPos < len) {
1691526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                value = pduDataStream.read();
1692526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                if (value == PduPart.P_FILENAME) { //filename is text-string
1693526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    part.setFilename(parseWapString(pduDataStream
1694526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                            , TYPE_TEXT_STRING));
1695526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                }
1696526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1697526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                /* skip other parameters */
1698526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                thisEndPos = pduDataStream.available();
1699526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                if (thisStartPos - thisEndPos < len) {
1700526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    int last = len - (thisStartPos - thisEndPos);
1701526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    byte[] temp = new byte[last];
1702526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                    pduDataStream.read(temp, 0, last);
1703526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                                }
1704526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            }
1705526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1706526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            tempPos = pduDataStream.available();
1707526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            lastLen = length - (startPos - tempPos);
1708526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
1709526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        break;
1710526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    default:
1711526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        if (LOCAL_LOGV) {
1712526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                            Log.v(LOG_TAG, "Not supported Part headers: " + header);
1713526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        }
1714526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    if (-1 == skipWapValue(pduDataStream, lastLen)) {
1715526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        Log.e(LOG_TAG, "Corrupt Part headers");
1716526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                        return false;
1717526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    }
1718526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    lastLen = 0;
1719526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    break;
1720526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1721526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } else if ((header >= TEXT_MIN) && (header <= TEXT_MAX)) {
1722526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Not assigned header.
1723526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] tempHeader = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1724526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] tempValue = parseWapString(pduDataStream, TYPE_TEXT_STRING);
1725526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1726526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Check the header whether it is "Content-Transfer-Encoding".
1727526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (true ==
1728526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    PduPart.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(new String(tempHeader))) {
1729526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    part.setContentTransferEncoding(tempValue);
1730526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1731526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1732526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                tempPos = pduDataStream.available();
1733526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                lastLen = length - (startPos - tempPos);
1734526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            } else {
1735526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (LOCAL_LOGV) {
1736526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.v(LOG_TAG, "Not supported Part headers: " + header);
1737526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1738526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Skip all headers of this part.
1739526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (-1 == skipWapValue(pduDataStream, lastLen)) {
1740526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    Log.e(LOG_TAG, "Corrupt Part headers");
1741526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1742526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1743526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                lastLen = 0;
1744526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
1745526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1746526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1747526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (0 != lastLen) {
1748526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            Log.e(LOG_TAG, "Corrupt Part headers");
1749526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return false;
1750526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1751526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1752526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return true;
1753526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1754526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1755526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1756526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Check the position of a specified part.
1757526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1758526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param part the part to be checked
1759526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return part position, THE_FIRST_PART when it's the
1760526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * first one, THE_LAST_PART when it's the last one.
1761526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1762526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    private static int checkPartPosition(PduPart part) {
1763526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        assert(null != part);
1764526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if ((null == mTypeParam) &&
1765526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                (null == mStartParam)) {
1766526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return THE_LAST_PART;
1767526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1768526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1769526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /* check part's content-id */
1770526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (null != mStartParam) {
1771526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            byte[] contentId = part.getContentId();
1772526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (null != contentId) {
1773526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (true == Arrays.equals(mStartParam, contentId)) {
1774526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return THE_FIRST_PART;
1775526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1776526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
17777c0f4b973245126bd4cca33eb3c5d53b99e9b51aYe Wen            // This is not the first part, so append to end (keeping the original order)
17787c0f4b973245126bd4cca33eb3c5d53b99e9b51aYe Wen            // Check b/19607294 for details of this change
17797c0f4b973245126bd4cca33eb3c5d53b99e9b51aYe Wen            return THE_LAST_PART;
1780526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1781526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1782526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /* check part's content-type */
1783526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (null != mTypeParam) {
1784526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            byte[] contentType = part.getContentType();
1785526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            if (null != contentType) {
1786526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (true == Arrays.equals(mTypeParam, contentType)) {
1787526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return THE_FIRST_PART;
1788526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1789526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            }
1790526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1791526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1792526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return THE_LAST_PART;
1793526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
1794526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1795526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    /**
1796526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * Check mandatory headers of a pdu.
1797526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     *
1798526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @param headers pdu headers
1799526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     * @return true if the pdu has all of the mandatory headers, false otherwise.
1800526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen     */
1801526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    protected static boolean checkMandatoryHeader(PduHeaders headers) {
1802526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (null == headers) {
1803526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return false;
1804526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1805526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1806526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /* get message type */
1807526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int messageType = headers.getOctet(PduHeaders.MESSAGE_TYPE);
1808526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1809526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /* check Mms-Version field */
1810526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        int mmsVersion = headers.getOctet(PduHeaders.MMS_VERSION);
1811526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        if (0 == mmsVersion) {
1812526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            // Every message should have Mms-Version field.
1813526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            return false;
1814526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
1815526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1816526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        /* check mandatory header fields */
1817526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        switch (messageType) {
1818526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
1819526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Content-Type field.
1820526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] srContentType = headers.getTextString(PduHeaders.CONTENT_TYPE);
1821526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == srContentType) {
1822526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1823526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1824526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1825526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // From field.
1826526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                EncodedStringValue srFrom = headers.getEncodedStringValue(PduHeaders.FROM);
1827526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == srFrom) {
1828526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1829526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1830526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1831526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Transaction-Id field.
1832526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] srTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
1833526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == srTransactionId) {
1834526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1835526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1836526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1837526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                break;
1838526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_SEND_CONF:
1839526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Response-Status field.
1840526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                int scResponseStatus = headers.getOctet(PduHeaders.RESPONSE_STATUS);
1841526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (0 == scResponseStatus) {
1842526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1843526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1844526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1845526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Transaction-Id field.
1846526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] scTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
1847526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == scTransactionId) {
1848526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1849526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1850526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1851526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                break;
1852526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
1853526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Content-Location field.
1854526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] niContentLocation = headers.getTextString(PduHeaders.CONTENT_LOCATION);
1855526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == niContentLocation) {
1856526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1857526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1858526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1859526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Expiry field.
1860526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                long niExpiry = headers.getLongInteger(PduHeaders.EXPIRY);
1861526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (-1 == niExpiry) {
1862526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1863526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1864526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1865526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Message-Class field.
1866526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] niMessageClass = headers.getTextString(PduHeaders.MESSAGE_CLASS);
1867526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == niMessageClass) {
1868526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1869526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1870526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1871526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Message-Size field.
1872526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                long niMessageSize = headers.getLongInteger(PduHeaders.MESSAGE_SIZE);
1873526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (-1 == niMessageSize) {
1874526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1875526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1876526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1877526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Transaction-Id field.
1878526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] niTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
1879526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == niTransactionId) {
1880526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1881526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1882526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1883526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                break;
1884526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
1885526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Status field.
1886526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                int nriStatus = headers.getOctet(PduHeaders.STATUS);
1887526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (0 == nriStatus) {
1888526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1889526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1890526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1891526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Transaction-Id field.
1892526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] nriTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
1893526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == nriTransactionId) {
1894526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1895526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1896526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1897526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                break;
1898526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF:
1899526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Content-Type field.
1900526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] rcContentType = headers.getTextString(PduHeaders.CONTENT_TYPE);
1901526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == rcContentType) {
1902526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1903526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1904526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1905526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Date field.
1906526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                long rcDate = headers.getLongInteger(PduHeaders.DATE);
1907526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (-1 == rcDate) {
1908526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1909526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1910526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1911526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                break;
1912526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
1913526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Date field.
1914526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                long diDate = headers.getLongInteger(PduHeaders.DATE);
1915526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (-1 == diDate) {
1916526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1917526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1918526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1919526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Message-Id field.
1920526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] diMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
1921526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == diMessageId) {
1922526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1923526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1924526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1925526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Status field.
1926526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                int diStatus = headers.getOctet(PduHeaders.STATUS);
1927526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (0 == diStatus) {
1928526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1929526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1930526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1931526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // To field.
1932526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                EncodedStringValue[] diTo = headers.getEncodedStringValues(PduHeaders.TO);
1933526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == diTo) {
1934526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1935526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1936526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1937526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                break;
1938526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
1939526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Transaction-Id field.
1940526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] aiTransactionId = headers.getTextString(PduHeaders.TRANSACTION_ID);
1941526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == aiTransactionId) {
1942526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1943526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1944526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1945526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                break;
1946526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_READ_ORIG_IND:
1947526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Date field.
1948526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                long roDate = headers.getLongInteger(PduHeaders.DATE);
1949526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (-1 == roDate) {
1950526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1951526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1952526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1953526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // From field.
1954526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                EncodedStringValue roFrom = headers.getEncodedStringValue(PduHeaders.FROM);
1955526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == roFrom) {
1956526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1957526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1958526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1959526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Message-Id field.
1960526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] roMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
1961526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == roMessageId) {
1962526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1963526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1964526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1965526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Read-Status field.
1966526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                int roReadStatus = headers.getOctet(PduHeaders.READ_STATUS);
1967526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (0 == roReadStatus) {
1968526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1969526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1970526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1971526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // To field.
1972526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                EncodedStringValue[] roTo = headers.getEncodedStringValues(PduHeaders.TO);
1973526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == roTo) {
1974526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1975526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1976526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1977526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                break;
1978526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
1979526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // From field.
1980526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                EncodedStringValue rrFrom = headers.getEncodedStringValue(PduHeaders.FROM);
1981526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == rrFrom) {
1982526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1983526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1984526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1985526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Message-Id field.
1986526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                byte[] rrMessageId = headers.getTextString(PduHeaders.MESSAGE_ID);
1987526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == rrMessageId) {
1988526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1989526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1990526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1991526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Read-Status field.
1992526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                int rrReadStatus = headers.getOctet(PduHeaders.READ_STATUS);
1993526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (0 == rrReadStatus) {
1994526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
1995526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
1996526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
1997526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // To field.
1998526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                EncodedStringValue[] rrTo = headers.getEncodedStringValues(PduHeaders.TO);
1999526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                if (null == rrTo) {
2000526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                    return false;
2001526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                }
2002526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
2003526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                break;
2004526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen            default:
2005526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                // Parser doesn't support this message type in this version.
2006526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen                return false;
2007526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        }
2008526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen
2009526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen        return true;
2010526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen    }
2011526ecd1799a2fc467cfce114eae3578b42ccb786Ye Wen}
2012