| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.internal.telephony; |
| |
| import android.compat.annotation.UnsupportedAppUsage; |
| |
| import java.util.HashMap; |
| |
| /** |
| * Implement the WSP data type decoder. |
| * |
| * @hide |
| */ |
| public class WspTypeDecoder { |
| |
| private static final int WAP_PDU_SHORT_LENGTH_MAX = 30; |
| private static final int WAP_PDU_LENGTH_QUOTE = 31; |
| |
| public static final int PDU_TYPE_PUSH = 0x06; |
| public static final int PDU_TYPE_CONFIRMED_PUSH = 0x07; |
| |
| private final static HashMap<Integer, String> WELL_KNOWN_MIME_TYPES = |
| new HashMap<Integer, String>(); |
| |
| private final static HashMap<Integer, String> WELL_KNOWN_PARAMETERS = |
| new HashMap<Integer, String>(); |
| |
| public static final int PARAMETER_ID_X_WAP_APPLICATION_ID = 0x2f; |
| private static final int Q_VALUE = 0x00; |
| |
| static { |
| WELL_KNOWN_MIME_TYPES.put(0x00, "*/*"); |
| WELL_KNOWN_MIME_TYPES.put(0x01, "text/*"); |
| WELL_KNOWN_MIME_TYPES.put(0x02, "text/html"); |
| WELL_KNOWN_MIME_TYPES.put(0x03, "text/plain"); |
| WELL_KNOWN_MIME_TYPES.put(0x04, "text/x-hdml"); |
| WELL_KNOWN_MIME_TYPES.put(0x05, "text/x-ttml"); |
| WELL_KNOWN_MIME_TYPES.put(0x06, "text/x-vCalendar"); |
| WELL_KNOWN_MIME_TYPES.put(0x07, "text/x-vCard"); |
| WELL_KNOWN_MIME_TYPES.put(0x08, "text/vnd.wap.wml"); |
| WELL_KNOWN_MIME_TYPES.put(0x09, "text/vnd.wap.wmlscript"); |
| WELL_KNOWN_MIME_TYPES.put(0x0A, "text/vnd.wap.wta-event"); |
| WELL_KNOWN_MIME_TYPES.put(0x0B, "multipart/*"); |
| WELL_KNOWN_MIME_TYPES.put(0x0C, "multipart/mixed"); |
| WELL_KNOWN_MIME_TYPES.put(0x0D, "multipart/form-data"); |
| WELL_KNOWN_MIME_TYPES.put(0x0E, "multipart/byterantes"); |
| WELL_KNOWN_MIME_TYPES.put(0x0F, "multipart/alternative"); |
| WELL_KNOWN_MIME_TYPES.put(0x10, "application/*"); |
| WELL_KNOWN_MIME_TYPES.put(0x11, "application/java-vm"); |
| WELL_KNOWN_MIME_TYPES.put(0x12, "application/x-www-form-urlencoded"); |
| WELL_KNOWN_MIME_TYPES.put(0x13, "application/x-hdmlc"); |
| WELL_KNOWN_MIME_TYPES.put(0x14, "application/vnd.wap.wmlc"); |
| WELL_KNOWN_MIME_TYPES.put(0x15, "application/vnd.wap.wmlscriptc"); |
| WELL_KNOWN_MIME_TYPES.put(0x16, "application/vnd.wap.wta-eventc"); |
| WELL_KNOWN_MIME_TYPES.put(0x17, "application/vnd.wap.uaprof"); |
| WELL_KNOWN_MIME_TYPES.put(0x18, "application/vnd.wap.wtls-ca-certificate"); |
| WELL_KNOWN_MIME_TYPES.put(0x19, "application/vnd.wap.wtls-user-certificate"); |
| WELL_KNOWN_MIME_TYPES.put(0x1A, "application/x-x509-ca-cert"); |
| WELL_KNOWN_MIME_TYPES.put(0x1B, "application/x-x509-user-cert"); |
| WELL_KNOWN_MIME_TYPES.put(0x1C, "image/*"); |
| WELL_KNOWN_MIME_TYPES.put(0x1D, "image/gif"); |
| WELL_KNOWN_MIME_TYPES.put(0x1E, "image/jpeg"); |
| WELL_KNOWN_MIME_TYPES.put(0x1F, "image/tiff"); |
| WELL_KNOWN_MIME_TYPES.put(0x20, "image/png"); |
| WELL_KNOWN_MIME_TYPES.put(0x21, "image/vnd.wap.wbmp"); |
| WELL_KNOWN_MIME_TYPES.put(0x22, "application/vnd.wap.multipart.*"); |
| WELL_KNOWN_MIME_TYPES.put(0x23, "application/vnd.wap.multipart.mixed"); |
| WELL_KNOWN_MIME_TYPES.put(0x24, "application/vnd.wap.multipart.form-data"); |
| WELL_KNOWN_MIME_TYPES.put(0x25, "application/vnd.wap.multipart.byteranges"); |
| WELL_KNOWN_MIME_TYPES.put(0x26, "application/vnd.wap.multipart.alternative"); |
| WELL_KNOWN_MIME_TYPES.put(0x27, "application/xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x28, "text/xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x29, "application/vnd.wap.wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x2A, "application/x-x968-cross-cert"); |
| WELL_KNOWN_MIME_TYPES.put(0x2B, "application/x-x968-ca-cert"); |
| WELL_KNOWN_MIME_TYPES.put(0x2C, "application/x-x968-user-cert"); |
| WELL_KNOWN_MIME_TYPES.put(0x2D, "text/vnd.wap.si"); |
| WELL_KNOWN_MIME_TYPES.put(0x2E, "application/vnd.wap.sic"); |
| WELL_KNOWN_MIME_TYPES.put(0x2F, "text/vnd.wap.sl"); |
| WELL_KNOWN_MIME_TYPES.put(0x30, "application/vnd.wap.slc"); |
| WELL_KNOWN_MIME_TYPES.put(0x31, "text/vnd.wap.co"); |
| WELL_KNOWN_MIME_TYPES.put(0x32, "application/vnd.wap.coc"); |
| WELL_KNOWN_MIME_TYPES.put(0x33, "application/vnd.wap.multipart.related"); |
| WELL_KNOWN_MIME_TYPES.put(0x34, "application/vnd.wap.sia"); |
| WELL_KNOWN_MIME_TYPES.put(0x35, "text/vnd.wap.connectivity-xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x36, "application/vnd.wap.connectivity-wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x37, "application/pkcs7-mime"); |
| WELL_KNOWN_MIME_TYPES.put(0x38, "application/vnd.wap.hashed-certificate"); |
| WELL_KNOWN_MIME_TYPES.put(0x39, "application/vnd.wap.signed-certificate"); |
| WELL_KNOWN_MIME_TYPES.put(0x3A, "application/vnd.wap.cert-response"); |
| WELL_KNOWN_MIME_TYPES.put(0x3B, "application/xhtml+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x3C, "application/wml+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x3D, "text/css"); |
| WELL_KNOWN_MIME_TYPES.put(0x3E, "application/vnd.wap.mms-message"); |
| WELL_KNOWN_MIME_TYPES.put(0x3F, "application/vnd.wap.rollover-certificate"); |
| WELL_KNOWN_MIME_TYPES.put(0x40, "application/vnd.wap.locc+wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x41, "application/vnd.wap.loc+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x42, "application/vnd.syncml.dm+wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x43, "application/vnd.syncml.dm+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x44, "application/vnd.syncml.notification"); |
| WELL_KNOWN_MIME_TYPES.put(0x45, "application/vnd.wap.xhtml+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x46, "application/vnd.wv.csp.cir"); |
| WELL_KNOWN_MIME_TYPES.put(0x47, "application/vnd.oma.dd+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x48, "application/vnd.oma.drm.message"); |
| WELL_KNOWN_MIME_TYPES.put(0x49, "application/vnd.oma.drm.content"); |
| WELL_KNOWN_MIME_TYPES.put(0x4A, "application/vnd.oma.drm.rights+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x4B, "application/vnd.oma.drm.rights+wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x4C, "application/vnd.wv.csp+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x4D, "application/vnd.wv.csp+wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x4E, "application/vnd.syncml.ds.notification"); |
| WELL_KNOWN_MIME_TYPES.put(0x4F, "audio/*"); |
| WELL_KNOWN_MIME_TYPES.put(0x50, "video/*"); |
| WELL_KNOWN_MIME_TYPES.put(0x51, "application/vnd.oma.dd2+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x52, "application/mikey"); |
| WELL_KNOWN_MIME_TYPES.put(0x53, "application/vnd.oma.dcd"); |
| WELL_KNOWN_MIME_TYPES.put(0x54, "application/vnd.oma.dcdc"); |
| |
| WELL_KNOWN_MIME_TYPES.put(0x0201, "application/vnd.uplanet.cacheop-wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0202, "application/vnd.uplanet.signal"); |
| WELL_KNOWN_MIME_TYPES.put(0x0203, "application/vnd.uplanet.alert-wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0204, "application/vnd.uplanet.list-wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0205, "application/vnd.uplanet.listcmd-wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0206, "application/vnd.uplanet.channel-wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0207, "application/vnd.uplanet.provisioning-status-uri"); |
| WELL_KNOWN_MIME_TYPES.put(0x0208, "x-wap.multipart/vnd.uplanet.header-set"); |
| WELL_KNOWN_MIME_TYPES.put(0x0209, "application/vnd.uplanet.bearer-choice-wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x020A, "application/vnd.phonecom.mmc-wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x020B, "application/vnd.nokia.syncset+wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x020C, "image/x-up-wpng"); |
| WELL_KNOWN_MIME_TYPES.put(0x0300, "application/iota.mmc-wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0301, "application/iota.mmc-xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0302, "application/vnd.syncml+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0303, "application/vnd.syncml+wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0304, "text/vnd.wap.emn+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0305, "text/calendar"); |
| WELL_KNOWN_MIME_TYPES.put(0x0306, "application/vnd.omads-email+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0307, "application/vnd.omads-file+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0308, "application/vnd.omads-folder+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0309, "text/directory;profile=vCard"); |
| WELL_KNOWN_MIME_TYPES.put(0x030A, "application/vnd.wap.emn+wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x030B, "application/vnd.nokia.ipdc-purchase-response"); |
| WELL_KNOWN_MIME_TYPES.put(0x030C, "application/vnd.motorola.screen3+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x030D, "application/vnd.motorola.screen3+gzip"); |
| WELL_KNOWN_MIME_TYPES.put(0x030E, "application/vnd.cmcc.setting+wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x030F, "application/vnd.cmcc.bombing+wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0310, "application/vnd.docomo.pf"); |
| WELL_KNOWN_MIME_TYPES.put(0x0311, "application/vnd.docomo.ub"); |
| WELL_KNOWN_MIME_TYPES.put(0x0312, "application/vnd.omaloc-supl-init"); |
| WELL_KNOWN_MIME_TYPES.put(0x0313, "application/vnd.oma.group-usage-list+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0314, "application/oma-directory+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0315, "application/vnd.docomo.pf2"); |
| WELL_KNOWN_MIME_TYPES.put(0x0316, "application/vnd.oma.drm.roap-trigger+wbxml"); |
| WELL_KNOWN_MIME_TYPES.put(0x0317, "application/vnd.sbm.mid2"); |
| WELL_KNOWN_MIME_TYPES.put(0x0318, "application/vnd.wmf.bootstrap"); |
| WELL_KNOWN_MIME_TYPES.put(0x0319, "application/vnc.cmcc.dcd+xml"); |
| WELL_KNOWN_MIME_TYPES.put(0x031A, "application/vnd.sbm.cid"); |
| WELL_KNOWN_MIME_TYPES.put(0x031B, "application/vnd.oma.bcast.provisioningtrigger"); |
| |
| WELL_KNOWN_PARAMETERS.put(0x00, "Q"); |
| WELL_KNOWN_PARAMETERS.put(0x01, "Charset"); |
| WELL_KNOWN_PARAMETERS.put(0x02, "Level"); |
| WELL_KNOWN_PARAMETERS.put(0x03, "Type"); |
| WELL_KNOWN_PARAMETERS.put(0x07, "Differences"); |
| WELL_KNOWN_PARAMETERS.put(0x08, "Padding"); |
| WELL_KNOWN_PARAMETERS.put(0x09, "Type"); |
| WELL_KNOWN_PARAMETERS.put(0x0E, "Max-Age"); |
| WELL_KNOWN_PARAMETERS.put(0x10, "Secure"); |
| WELL_KNOWN_PARAMETERS.put(0x11, "SEC"); |
| WELL_KNOWN_PARAMETERS.put(0x12, "MAC"); |
| WELL_KNOWN_PARAMETERS.put(0x13, "Creation-date"); |
| WELL_KNOWN_PARAMETERS.put(0x14, "Modification-date"); |
| WELL_KNOWN_PARAMETERS.put(0x15, "Read-date"); |
| WELL_KNOWN_PARAMETERS.put(0x16, "Size"); |
| WELL_KNOWN_PARAMETERS.put(0x17, "Name"); |
| WELL_KNOWN_PARAMETERS.put(0x18, "Filename"); |
| WELL_KNOWN_PARAMETERS.put(0x19, "Start"); |
| WELL_KNOWN_PARAMETERS.put(0x1A, "Start-info"); |
| WELL_KNOWN_PARAMETERS.put(0x1B, "Comment"); |
| WELL_KNOWN_PARAMETERS.put(0x1C, "Domain"); |
| WELL_KNOWN_PARAMETERS.put(0x1D, "Path"); |
| } |
| |
| public static final String CONTENT_TYPE_B_PUSH_CO = "application/vnd.wap.coc"; |
| public static final String CONTENT_TYPE_B_MMS = "application/vnd.wap.mms-message"; |
| public static final String CONTENT_TYPE_B_PUSH_SYNCML_NOTI = "application/vnd.syncml.notification"; |
| |
| @UnsupportedAppUsage |
| byte[] mWspData; |
| int mDataLength; |
| long mUnsigned32bit; |
| String mStringValue; |
| |
| HashMap<String, String> mContentParameters; |
| |
| @UnsupportedAppUsage |
| public WspTypeDecoder(byte[] pdu) { |
| mWspData = pdu; |
| } |
| |
| /** |
| * Decode the "Text-string" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "Text-string" in this pdu |
| * |
| * @return false when error(not a Text-string) occur |
| * return value can be retrieved by getValueString() method length of data in pdu can be |
| * retrieved by getDecodedDataLength() method |
| */ |
| @UnsupportedAppUsage |
| public boolean decodeTextString(int startIndex) { |
| int index = startIndex; |
| while (mWspData[index] != 0) { |
| index++; |
| } |
| mDataLength = index - startIndex + 1; |
| if (mWspData[startIndex] == 127) { |
| mStringValue = new String(mWspData, startIndex + 1, mDataLength - 2); |
| } else { |
| mStringValue = new String(mWspData, startIndex, mDataLength - 1); |
| } |
| return true; |
| } |
| |
| /** |
| * Decode the "Token-text" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "Token-text" in this pdu |
| * |
| * @return always true |
| * return value can be retrieved by getValueString() method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| public boolean decodeTokenText(int startIndex) { |
| int index = startIndex; |
| while (mWspData[index] != 0) { |
| index++; |
| } |
| mDataLength = index - startIndex + 1; |
| mStringValue = new String(mWspData, startIndex, mDataLength - 1); |
| |
| return true; |
| } |
| |
| /** |
| * Decode the "Short-integer" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "Short-integer" in this pdu |
| * |
| * @return false when error(not a Short-integer) occur |
| * return value can be retrieved by getValue32() method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| @UnsupportedAppUsage |
| public boolean decodeShortInteger(int startIndex) { |
| if ((mWspData[startIndex] & 0x80) == 0) { |
| return false; |
| } |
| mUnsigned32bit = mWspData[startIndex] & 0x7f; |
| mDataLength = 1; |
| return true; |
| } |
| |
| /** |
| * Decode the "Long-integer" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "Long-integer" in this pdu |
| * |
| * @return false when error(not a Long-integer) occur |
| * return value can be retrieved by getValue32() method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| public boolean decodeLongInteger(int startIndex) { |
| int lengthMultiOctet = mWspData[startIndex] & 0xff; |
| |
| if (lengthMultiOctet > WAP_PDU_SHORT_LENGTH_MAX) { |
| return false; |
| } |
| mUnsigned32bit = 0; |
| for (int i = 1; i <= lengthMultiOctet; i++) { |
| mUnsigned32bit = (mUnsigned32bit << 8) | (mWspData[startIndex + i] & 0xff); |
| } |
| mDataLength = 1 + lengthMultiOctet; |
| return true; |
| } |
| |
| /** |
| * Decode the "Integer-Value" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "Integer-Value" in this pdu |
| * |
| * @return false when error(not a Integer-Value) occur |
| * return value can be retrieved by getValue32() method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| @UnsupportedAppUsage |
| public boolean decodeIntegerValue(int startIndex) { |
| if (decodeShortInteger(startIndex) == true) { |
| return true; |
| } |
| return decodeLongInteger(startIndex); |
| } |
| |
| /** |
| * Decode the "Uintvar-integer" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "Uintvar-integer" in this pdu |
| * |
| * @return false when error(not a Uintvar-integer) occur |
| * return value can be retrieved by getValue32() method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| @UnsupportedAppUsage |
| public boolean decodeUintvarInteger(int startIndex) { |
| int index = startIndex; |
| |
| mUnsigned32bit = 0; |
| while ((mWspData[index] & 0x80) != 0) { |
| if ((index - startIndex) >= 4) { |
| return false; |
| } |
| mUnsigned32bit = (mUnsigned32bit << 7) | (mWspData[index] & 0x7f); |
| index++; |
| } |
| mUnsigned32bit = (mUnsigned32bit << 7) | (mWspData[index] & 0x7f); |
| mDataLength = index - startIndex + 1; |
| return true; |
| } |
| |
| /** |
| * Decode the "Value-length" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "Value-length" in this pdu |
| * |
| * @return false when error(not a Value-length) occur |
| * return value can be retrieved by getValue32() method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| @UnsupportedAppUsage |
| public boolean decodeValueLength(int startIndex) { |
| if ((mWspData[startIndex] & 0xff) > WAP_PDU_LENGTH_QUOTE) { |
| return false; |
| } |
| if (mWspData[startIndex] < WAP_PDU_LENGTH_QUOTE) { |
| mUnsigned32bit = mWspData[startIndex]; |
| mDataLength = 1; |
| } else { |
| decodeUintvarInteger(startIndex + 1); |
| mDataLength++; |
| } |
| return true; |
| } |
| |
| /** |
| * Decode the "Extension-media" type for WSP PDU. |
| * |
| * @param startIndex The starting position of the "Extension-media" in this PDU. |
| * |
| * @return false on error, such as if there is no Extension-media at startIndex. |
| * Side-effects: updates stringValue (available with |
| * getValueString()), which will be null on error. The length of the |
| * data in the PDU is available with getValue32(), 0 on error. |
| */ |
| public boolean decodeExtensionMedia(int startIndex) { |
| int index = startIndex; |
| mDataLength = 0; |
| mStringValue = null; |
| int length = mWspData.length; |
| boolean rtrn = index < length; |
| |
| while (index < length && mWspData[index] != 0) { |
| index++; |
| } |
| |
| mDataLength = index - startIndex + 1; |
| mStringValue = new String(mWspData, startIndex, mDataLength - 1); |
| |
| return rtrn; |
| } |
| |
| /** |
| * Decode the "Constrained-encoding" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "Constrained-encoding" in this pdu |
| * |
| * @return false when error(not a Constrained-encoding) occur |
| * return value can be retrieved first by getValueString() and second by getValue32() method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| public boolean decodeConstrainedEncoding(int startIndex) { |
| if (decodeShortInteger(startIndex) == true) { |
| mStringValue = null; |
| return true; |
| } |
| return decodeExtensionMedia(startIndex); |
| } |
| |
| /** |
| * Decode the "Content-type" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "Content-type" in this pdu |
| * |
| * @return false when error(not a Content-type) occurs |
| * If a content type exists in the headers (either as inline string, or as well-known |
| * value), getValueString() will return it. If a 'well known value' is encountered that |
| * cannot be mapped to a string mime type, getValueString() will return null, and |
| * getValue32() will return the unknown content type value. |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| * Any content type parameters will be accessible via getContentParameters() |
| */ |
| @UnsupportedAppUsage |
| public boolean decodeContentType(int startIndex) { |
| int mediaPrefixLength; |
| mContentParameters = new HashMap<String, String>(); |
| |
| try { |
| if (decodeValueLength(startIndex) == false) { |
| boolean found = decodeConstrainedEncoding(startIndex); |
| if (found) { |
| expandWellKnownMimeType(); |
| } |
| return found; |
| } |
| int headersLength = (int) mUnsigned32bit; |
| mediaPrefixLength = getDecodedDataLength(); |
| if (decodeIntegerValue(startIndex + mediaPrefixLength) == true) { |
| mDataLength += mediaPrefixLength; |
| int readLength = mDataLength; |
| mStringValue = null; |
| expandWellKnownMimeType(); |
| long wellKnownValue = mUnsigned32bit; |
| String mimeType = mStringValue; |
| if (readContentParameters(startIndex + mDataLength, |
| (headersLength - (mDataLength - mediaPrefixLength)), 0)) { |
| mDataLength += readLength; |
| mUnsigned32bit = wellKnownValue; |
| mStringValue = mimeType; |
| return true; |
| } |
| return false; |
| } |
| if (decodeExtensionMedia(startIndex + mediaPrefixLength) == true) { |
| mDataLength += mediaPrefixLength; |
| int readLength = mDataLength; |
| expandWellKnownMimeType(); |
| long wellKnownValue = mUnsigned32bit; |
| String mimeType = mStringValue; |
| if (readContentParameters(startIndex + mDataLength, |
| (headersLength - (mDataLength - mediaPrefixLength)), 0)) { |
| mDataLength += readLength; |
| mUnsigned32bit = wellKnownValue; |
| mStringValue = mimeType; |
| return true; |
| } |
| } |
| } catch (ArrayIndexOutOfBoundsException e) { |
| //something doesn't add up |
| return false; |
| } |
| return false; |
| } |
| |
| private boolean readContentParameters(int startIndex, int leftToRead, int accumulator) { |
| |
| int totalRead = 0; |
| |
| if (leftToRead > 0) { |
| byte nextByte = mWspData[startIndex]; |
| String value = null; |
| String param = null; |
| if ((nextByte & 0x80) == 0x00 && nextByte > 31) { // untyped |
| decodeTokenText(startIndex); |
| param = mStringValue; |
| totalRead += mDataLength; |
| } else { // typed |
| if (decodeIntegerValue(startIndex)) { |
| totalRead += mDataLength; |
| int wellKnownParameterValue = (int) mUnsigned32bit; |
| param = WELL_KNOWN_PARAMETERS.get(wellKnownParameterValue); |
| if (param == null) { |
| param = "unassigned/0x" + Long.toHexString(wellKnownParameterValue); |
| } |
| // special case for the "Q" parameter, value is a uintvar |
| if (wellKnownParameterValue == Q_VALUE) { |
| if (decodeUintvarInteger(startIndex + totalRead)) { |
| totalRead += mDataLength; |
| value = String.valueOf(mUnsigned32bit); |
| mContentParameters.put(param, value); |
| return readContentParameters(startIndex + totalRead, leftToRead |
| - totalRead, accumulator + totalRead); |
| } else { |
| return false; |
| } |
| } |
| } else { |
| return false; |
| } |
| } |
| |
| if (decodeNoValue(startIndex + totalRead)) { |
| totalRead += mDataLength; |
| value = null; |
| } else if (decodeIntegerValue(startIndex + totalRead)) { |
| totalRead += mDataLength; |
| int intValue = (int) mUnsigned32bit; |
| value = String.valueOf(intValue); |
| } else { |
| decodeTokenText(startIndex + totalRead); |
| totalRead += mDataLength; |
| value = mStringValue; |
| if (value.startsWith("\"")) { |
| // quoted string, so remove the quote |
| value = value.substring(1); |
| } |
| } |
| mContentParameters.put(param, value); |
| return readContentParameters(startIndex + totalRead, leftToRead - totalRead, |
| accumulator + totalRead); |
| |
| } else { |
| mDataLength = accumulator; |
| return true; |
| } |
| } |
| |
| /** |
| * Check if the next byte is No-Value |
| * |
| * @param startIndex The starting position of the "Content length" in this pdu |
| * |
| * @return true if and only if the next byte is 0x00 |
| */ |
| private boolean decodeNoValue(int startIndex) { |
| if (mWspData[startIndex] == 0) { |
| mDataLength = 1; |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| /** |
| * Populate stringValue with the mime type corresponding to the value in unsigned32bit |
| * |
| * Sets unsigned32bit to -1 if stringValue is already populated |
| */ |
| private void expandWellKnownMimeType() { |
| if (mStringValue == null) { |
| int binaryContentType = (int) mUnsigned32bit; |
| mStringValue = WELL_KNOWN_MIME_TYPES.get(binaryContentType); |
| } else { |
| mUnsigned32bit = -1; |
| } |
| } |
| |
| /** |
| * Decode the "Content length" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "Content length" in this pdu |
| * |
| * @return false when error(not a Content length) occur |
| * return value can be retrieved by getValue32() method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| public boolean decodeContentLength(int startIndex) { |
| return decodeIntegerValue(startIndex); |
| } |
| |
| /** |
| * Decode the "Content location" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "Content location" in this pdu |
| * |
| * @return false when error(not a Content location) occur |
| * return value can be retrieved by getValueString() method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| public boolean decodeContentLocation(int startIndex) { |
| return decodeTextString(startIndex); |
| } |
| |
| /** |
| * Decode the "X-Wap-Application-Id" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "X-Wap-Application-Id" in this pdu |
| * |
| * @return false when error(not a X-Wap-Application-Id) occur |
| * return value can be retrieved first by getValueString() and second by getValue32() |
| * method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| @UnsupportedAppUsage |
| public boolean decodeXWapApplicationId(int startIndex) { |
| if (decodeIntegerValue(startIndex) == true) { |
| mStringValue = null; |
| return true; |
| } |
| return decodeTextString(startIndex); |
| } |
| |
| /** |
| * Seek for the "X-Wap-Application-Id" field for WSP pdu |
| * |
| * @param startIndex The starting position of seek pointer |
| * @param endIndex Valid seek area end point |
| * |
| * @return false when error(not a X-Wap-Application-Id) occur |
| * return value can be retrieved by getValue32() |
| */ |
| @UnsupportedAppUsage |
| public boolean seekXWapApplicationId(int startIndex, int endIndex) { |
| int index = startIndex; |
| |
| try { |
| for (index = startIndex; index <= endIndex; ) { |
| /** |
| * 8.4.1.1 Field name |
| * Field name is integer or text. |
| */ |
| if (decodeIntegerValue(index)) { |
| int fieldValue = (int) getValue32(); |
| |
| if (fieldValue == PARAMETER_ID_X_WAP_APPLICATION_ID) { |
| mUnsigned32bit = index + 1; |
| return true; |
| } |
| } else { |
| if (!decodeTextString(index)) return false; |
| } |
| index += getDecodedDataLength(); |
| if (index > endIndex) return false; |
| |
| /** |
| * 8.4.1.2 Field values |
| * Value Interpretation of First Octet |
| * 0 - 30 This octet is followed by the indicated number (0 - 30) |
| of data octets |
| * 31 This octet is followed by a uintvar, which indicates the number |
| * of data octets after it |
| * 32 - 127 The value is a text string, terminated by a zero octet |
| (NUL character) |
| * 128 - 255 It is an encoded 7-bit value; this header has no more data |
| */ |
| byte val = mWspData[index]; |
| if (0 <= val && val <= WAP_PDU_SHORT_LENGTH_MAX) { |
| index += mWspData[index] + 1; |
| } else if (val == WAP_PDU_LENGTH_QUOTE) { |
| if (index + 1 >= endIndex) return false; |
| index++; |
| if (!decodeUintvarInteger(index)) return false; |
| index += getDecodedDataLength(); |
| } else if (WAP_PDU_LENGTH_QUOTE < val && val <= 127) { |
| if (!decodeTextString(index)) return false; |
| index += getDecodedDataLength(); |
| } else { |
| index++; |
| } |
| } |
| } catch (ArrayIndexOutOfBoundsException e) { |
| //seek application ID failed. WSP header might be corrupted |
| return false; |
| } |
| return false; |
| } |
| |
| /** |
| * Decode the "X-Wap-Content-URI" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "X-Wap-Content-URI" in this pdu |
| * |
| * @return false when error(not a X-Wap-Content-URI) occur |
| * return value can be retrieved by getValueString() method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| public boolean decodeXWapContentURI(int startIndex) { |
| return decodeTextString(startIndex); |
| } |
| |
| /** |
| * Decode the "X-Wap-Initiator-URI" type for WSP pdu |
| * |
| * @param startIndex The starting position of the "X-Wap-Initiator-URI" in this pdu |
| * |
| * @return false when error(not a X-Wap-Initiator-URI) occur |
| * return value can be retrieved by getValueString() method |
| * length of data in pdu can be retrieved by getDecodedDataLength() method |
| */ |
| public boolean decodeXWapInitiatorURI(int startIndex) { |
| return decodeTextString(startIndex); |
| } |
| |
| /** |
| * The data length of latest operation. |
| */ |
| @UnsupportedAppUsage |
| public int getDecodedDataLength() { |
| return mDataLength; |
| } |
| |
| /** |
| * The 32-bits result of latest operation. |
| */ |
| @UnsupportedAppUsage |
| public long getValue32() { |
| return mUnsigned32bit; |
| } |
| |
| /** |
| * The String result of latest operation. |
| */ |
| @UnsupportedAppUsage |
| public String getValueString() { |
| return mStringValue; |
| } |
| |
| /** |
| * Any parameters encountered as part of a decodeContentType() invocation. |
| * |
| * @return a map of content parameters keyed by their names, or null if |
| * decodeContentType() has not been called If any unassigned |
| * well-known parameters are encountered, the key of the map will be |
| * 'unassigned/0x...', where '...' is the hex value of the |
| * unassigned parameter. If a parameter has No-Value the value will be null. |
| * |
| */ |
| @UnsupportedAppUsage |
| public HashMap<String, String> getContentParameters() { |
| return mContentParameters; |
| } |
| } |