1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 21 import java.util.HashMap; 22 23 /** 24 * Implement the WSP data type decoder. 25 * 26 * @hide 27 */ 28 public class WspTypeDecoder { 29 30 private static final int WAP_PDU_SHORT_LENGTH_MAX = 30; 31 private static final int WAP_PDU_LENGTH_QUOTE = 31; 32 33 public static final int PDU_TYPE_PUSH = 0x06; 34 public static final int PDU_TYPE_CONFIRMED_PUSH = 0x07; 35 36 private final static HashMap<Integer, String> WELL_KNOWN_MIME_TYPES = 37 new HashMap<Integer, String>(); 38 39 private final static HashMap<Integer, String> WELL_KNOWN_PARAMETERS = 40 new HashMap<Integer, String>(); 41 42 public static final int PARAMETER_ID_X_WAP_APPLICATION_ID = 0x2f; 43 private static final int Q_VALUE = 0x00; 44 45 static { 46 WELL_KNOWN_MIME_TYPES.put(0x00, "*/*"); 47 WELL_KNOWN_MIME_TYPES.put(0x01, "text/*"); 48 WELL_KNOWN_MIME_TYPES.put(0x02, "text/html"); 49 WELL_KNOWN_MIME_TYPES.put(0x03, "text/plain"); 50 WELL_KNOWN_MIME_TYPES.put(0x04, "text/x-hdml"); 51 WELL_KNOWN_MIME_TYPES.put(0x05, "text/x-ttml"); 52 WELL_KNOWN_MIME_TYPES.put(0x06, "text/x-vCalendar"); 53 WELL_KNOWN_MIME_TYPES.put(0x07, "text/x-vCard"); 54 WELL_KNOWN_MIME_TYPES.put(0x08, "text/vnd.wap.wml"); 55 WELL_KNOWN_MIME_TYPES.put(0x09, "text/vnd.wap.wmlscript"); 56 WELL_KNOWN_MIME_TYPES.put(0x0A, "text/vnd.wap.wta-event"); 57 WELL_KNOWN_MIME_TYPES.put(0x0B, "multipart/*"); 58 WELL_KNOWN_MIME_TYPES.put(0x0C, "multipart/mixed"); 59 WELL_KNOWN_MIME_TYPES.put(0x0D, "multipart/form-data"); 60 WELL_KNOWN_MIME_TYPES.put(0x0E, "multipart/byterantes"); 61 WELL_KNOWN_MIME_TYPES.put(0x0F, "multipart/alternative"); 62 WELL_KNOWN_MIME_TYPES.put(0x10, "application/*"); 63 WELL_KNOWN_MIME_TYPES.put(0x11, "application/java-vm"); 64 WELL_KNOWN_MIME_TYPES.put(0x12, "application/x-www-form-urlencoded"); 65 WELL_KNOWN_MIME_TYPES.put(0x13, "application/x-hdmlc"); 66 WELL_KNOWN_MIME_TYPES.put(0x14, "application/vnd.wap.wmlc"); 67 WELL_KNOWN_MIME_TYPES.put(0x15, "application/vnd.wap.wmlscriptc"); 68 WELL_KNOWN_MIME_TYPES.put(0x16, "application/vnd.wap.wta-eventc"); 69 WELL_KNOWN_MIME_TYPES.put(0x17, "application/vnd.wap.uaprof"); 70 WELL_KNOWN_MIME_TYPES.put(0x18, "application/vnd.wap.wtls-ca-certificate"); 71 WELL_KNOWN_MIME_TYPES.put(0x19, "application/vnd.wap.wtls-user-certificate"); 72 WELL_KNOWN_MIME_TYPES.put(0x1A, "application/x-x509-ca-cert"); 73 WELL_KNOWN_MIME_TYPES.put(0x1B, "application/x-x509-user-cert"); 74 WELL_KNOWN_MIME_TYPES.put(0x1C, "image/*"); 75 WELL_KNOWN_MIME_TYPES.put(0x1D, "image/gif"); 76 WELL_KNOWN_MIME_TYPES.put(0x1E, "image/jpeg"); 77 WELL_KNOWN_MIME_TYPES.put(0x1F, "image/tiff"); 78 WELL_KNOWN_MIME_TYPES.put(0x20, "image/png"); 79 WELL_KNOWN_MIME_TYPES.put(0x21, "image/vnd.wap.wbmp"); 80 WELL_KNOWN_MIME_TYPES.put(0x22, "application/vnd.wap.multipart.*"); 81 WELL_KNOWN_MIME_TYPES.put(0x23, "application/vnd.wap.multipart.mixed"); 82 WELL_KNOWN_MIME_TYPES.put(0x24, "application/vnd.wap.multipart.form-data"); 83 WELL_KNOWN_MIME_TYPES.put(0x25, "application/vnd.wap.multipart.byteranges"); 84 WELL_KNOWN_MIME_TYPES.put(0x26, "application/vnd.wap.multipart.alternative"); 85 WELL_KNOWN_MIME_TYPES.put(0x27, "application/xml"); 86 WELL_KNOWN_MIME_TYPES.put(0x28, "text/xml"); 87 WELL_KNOWN_MIME_TYPES.put(0x29, "application/vnd.wap.wbxml"); 88 WELL_KNOWN_MIME_TYPES.put(0x2A, "application/x-x968-cross-cert"); 89 WELL_KNOWN_MIME_TYPES.put(0x2B, "application/x-x968-ca-cert"); 90 WELL_KNOWN_MIME_TYPES.put(0x2C, "application/x-x968-user-cert"); 91 WELL_KNOWN_MIME_TYPES.put(0x2D, "text/vnd.wap.si"); 92 WELL_KNOWN_MIME_TYPES.put(0x2E, "application/vnd.wap.sic"); 93 WELL_KNOWN_MIME_TYPES.put(0x2F, "text/vnd.wap.sl"); 94 WELL_KNOWN_MIME_TYPES.put(0x30, "application/vnd.wap.slc"); 95 WELL_KNOWN_MIME_TYPES.put(0x31, "text/vnd.wap.co"); 96 WELL_KNOWN_MIME_TYPES.put(0x32, "application/vnd.wap.coc"); 97 WELL_KNOWN_MIME_TYPES.put(0x33, "application/vnd.wap.multipart.related"); 98 WELL_KNOWN_MIME_TYPES.put(0x34, "application/vnd.wap.sia"); 99 WELL_KNOWN_MIME_TYPES.put(0x35, "text/vnd.wap.connectivity-xml"); 100 WELL_KNOWN_MIME_TYPES.put(0x36, "application/vnd.wap.connectivity-wbxml"); 101 WELL_KNOWN_MIME_TYPES.put(0x37, "application/pkcs7-mime"); 102 WELL_KNOWN_MIME_TYPES.put(0x38, "application/vnd.wap.hashed-certificate"); 103 WELL_KNOWN_MIME_TYPES.put(0x39, "application/vnd.wap.signed-certificate"); 104 WELL_KNOWN_MIME_TYPES.put(0x3A, "application/vnd.wap.cert-response"); 105 WELL_KNOWN_MIME_TYPES.put(0x3B, "application/xhtml+xml"); 106 WELL_KNOWN_MIME_TYPES.put(0x3C, "application/wml+xml"); 107 WELL_KNOWN_MIME_TYPES.put(0x3D, "text/css"); 108 WELL_KNOWN_MIME_TYPES.put(0x3E, "application/vnd.wap.mms-message"); 109 WELL_KNOWN_MIME_TYPES.put(0x3F, "application/vnd.wap.rollover-certificate"); 110 WELL_KNOWN_MIME_TYPES.put(0x40, "application/vnd.wap.locc+wbxml"); 111 WELL_KNOWN_MIME_TYPES.put(0x41, "application/vnd.wap.loc+xml"); 112 WELL_KNOWN_MIME_TYPES.put(0x42, "application/vnd.syncml.dm+wbxml"); 113 WELL_KNOWN_MIME_TYPES.put(0x43, "application/vnd.syncml.dm+xml"); 114 WELL_KNOWN_MIME_TYPES.put(0x44, "application/vnd.syncml.notification"); 115 WELL_KNOWN_MIME_TYPES.put(0x45, "application/vnd.wap.xhtml+xml"); 116 WELL_KNOWN_MIME_TYPES.put(0x46, "application/vnd.wv.csp.cir"); 117 WELL_KNOWN_MIME_TYPES.put(0x47, "application/vnd.oma.dd+xml"); 118 WELL_KNOWN_MIME_TYPES.put(0x48, "application/vnd.oma.drm.message"); 119 WELL_KNOWN_MIME_TYPES.put(0x49, "application/vnd.oma.drm.content"); 120 WELL_KNOWN_MIME_TYPES.put(0x4A, "application/vnd.oma.drm.rights+xml"); 121 WELL_KNOWN_MIME_TYPES.put(0x4B, "application/vnd.oma.drm.rights+wbxml"); 122 WELL_KNOWN_MIME_TYPES.put(0x4C, "application/vnd.wv.csp+xml"); 123 WELL_KNOWN_MIME_TYPES.put(0x4D, "application/vnd.wv.csp+wbxml"); 124 WELL_KNOWN_MIME_TYPES.put(0x4E, "application/vnd.syncml.ds.notification"); 125 WELL_KNOWN_MIME_TYPES.put(0x4F, "audio/*"); 126 WELL_KNOWN_MIME_TYPES.put(0x50, "video/*"); 127 WELL_KNOWN_MIME_TYPES.put(0x51, "application/vnd.oma.dd2+xml"); 128 WELL_KNOWN_MIME_TYPES.put(0x52, "application/mikey"); 129 WELL_KNOWN_MIME_TYPES.put(0x53, "application/vnd.oma.dcd"); 130 WELL_KNOWN_MIME_TYPES.put(0x54, "application/vnd.oma.dcdc"); 131 132 WELL_KNOWN_MIME_TYPES.put(0x0201, "application/vnd.uplanet.cacheop-wbxml"); 133 WELL_KNOWN_MIME_TYPES.put(0x0202, "application/vnd.uplanet.signal"); 134 WELL_KNOWN_MIME_TYPES.put(0x0203, "application/vnd.uplanet.alert-wbxml"); 135 WELL_KNOWN_MIME_TYPES.put(0x0204, "application/vnd.uplanet.list-wbxml"); 136 WELL_KNOWN_MIME_TYPES.put(0x0205, "application/vnd.uplanet.listcmd-wbxml"); 137 WELL_KNOWN_MIME_TYPES.put(0x0206, "application/vnd.uplanet.channel-wbxml"); 138 WELL_KNOWN_MIME_TYPES.put(0x0207, "application/vnd.uplanet.provisioning-status-uri"); 139 WELL_KNOWN_MIME_TYPES.put(0x0208, "x-wap.multipart/vnd.uplanet.header-set"); 140 WELL_KNOWN_MIME_TYPES.put(0x0209, "application/vnd.uplanet.bearer-choice-wbxml"); 141 WELL_KNOWN_MIME_TYPES.put(0x020A, "application/vnd.phonecom.mmc-wbxml"); 142 WELL_KNOWN_MIME_TYPES.put(0x020B, "application/vnd.nokia.syncset+wbxml"); 143 WELL_KNOWN_MIME_TYPES.put(0x020C, "image/x-up-wpng"); 144 WELL_KNOWN_MIME_TYPES.put(0x0300, "application/iota.mmc-wbxml"); 145 WELL_KNOWN_MIME_TYPES.put(0x0301, "application/iota.mmc-xml"); 146 WELL_KNOWN_MIME_TYPES.put(0x0302, "application/vnd.syncml+xml"); 147 WELL_KNOWN_MIME_TYPES.put(0x0303, "application/vnd.syncml+wbxml"); 148 WELL_KNOWN_MIME_TYPES.put(0x0304, "text/vnd.wap.emn+xml"); 149 WELL_KNOWN_MIME_TYPES.put(0x0305, "text/calendar"); 150 WELL_KNOWN_MIME_TYPES.put(0x0306, "application/vnd.omads-email+xml"); 151 WELL_KNOWN_MIME_TYPES.put(0x0307, "application/vnd.omads-file+xml"); 152 WELL_KNOWN_MIME_TYPES.put(0x0308, "application/vnd.omads-folder+xml"); 153 WELL_KNOWN_MIME_TYPES.put(0x0309, "text/directory;profile=vCard"); 154 WELL_KNOWN_MIME_TYPES.put(0x030A, "application/vnd.wap.emn+wbxml"); 155 WELL_KNOWN_MIME_TYPES.put(0x030B, "application/vnd.nokia.ipdc-purchase-response"); 156 WELL_KNOWN_MIME_TYPES.put(0x030C, "application/vnd.motorola.screen3+xml"); 157 WELL_KNOWN_MIME_TYPES.put(0x030D, "application/vnd.motorola.screen3+gzip"); 158 WELL_KNOWN_MIME_TYPES.put(0x030E, "application/vnd.cmcc.setting+wbxml"); 159 WELL_KNOWN_MIME_TYPES.put(0x030F, "application/vnd.cmcc.bombing+wbxml"); 160 WELL_KNOWN_MIME_TYPES.put(0x0310, "application/vnd.docomo.pf"); 161 WELL_KNOWN_MIME_TYPES.put(0x0311, "application/vnd.docomo.ub"); 162 WELL_KNOWN_MIME_TYPES.put(0x0312, "application/vnd.omaloc-supl-init"); 163 WELL_KNOWN_MIME_TYPES.put(0x0313, "application/vnd.oma.group-usage-list+xml"); 164 WELL_KNOWN_MIME_TYPES.put(0x0314, "application/oma-directory+xml"); 165 WELL_KNOWN_MIME_TYPES.put(0x0315, "application/vnd.docomo.pf2"); 166 WELL_KNOWN_MIME_TYPES.put(0x0316, "application/vnd.oma.drm.roap-trigger+wbxml"); 167 WELL_KNOWN_MIME_TYPES.put(0x0317, "application/vnd.sbm.mid2"); 168 WELL_KNOWN_MIME_TYPES.put(0x0318, "application/vnd.wmf.bootstrap"); 169 WELL_KNOWN_MIME_TYPES.put(0x0319, "application/vnc.cmcc.dcd+xml"); 170 WELL_KNOWN_MIME_TYPES.put(0x031A, "application/vnd.sbm.cid"); 171 WELL_KNOWN_MIME_TYPES.put(0x031B, "application/vnd.oma.bcast.provisioningtrigger"); 172 173 WELL_KNOWN_PARAMETERS.put(0x00, "Q"); 174 WELL_KNOWN_PARAMETERS.put(0x01, "Charset"); 175 WELL_KNOWN_PARAMETERS.put(0x02, "Level"); 176 WELL_KNOWN_PARAMETERS.put(0x03, "Type"); 177 WELL_KNOWN_PARAMETERS.put(0x07, "Differences"); 178 WELL_KNOWN_PARAMETERS.put(0x08, "Padding"); 179 WELL_KNOWN_PARAMETERS.put(0x09, "Type"); 180 WELL_KNOWN_PARAMETERS.put(0x0E, "Max-Age"); 181 WELL_KNOWN_PARAMETERS.put(0x10, "Secure"); 182 WELL_KNOWN_PARAMETERS.put(0x11, "SEC"); 183 WELL_KNOWN_PARAMETERS.put(0x12, "MAC"); 184 WELL_KNOWN_PARAMETERS.put(0x13, "Creation-date"); 185 WELL_KNOWN_PARAMETERS.put(0x14, "Modification-date"); 186 WELL_KNOWN_PARAMETERS.put(0x15, "Read-date"); 187 WELL_KNOWN_PARAMETERS.put(0x16, "Size"); 188 WELL_KNOWN_PARAMETERS.put(0x17, "Name"); 189 WELL_KNOWN_PARAMETERS.put(0x18, "Filename"); 190 WELL_KNOWN_PARAMETERS.put(0x19, "Start"); 191 WELL_KNOWN_PARAMETERS.put(0x1A, "Start-info"); 192 WELL_KNOWN_PARAMETERS.put(0x1B, "Comment"); 193 WELL_KNOWN_PARAMETERS.put(0x1C, "Domain"); 194 WELL_KNOWN_PARAMETERS.put(0x1D, "Path"); 195 } 196 197 public static final String CONTENT_TYPE_B_PUSH_CO = "application/vnd.wap.coc"; 198 public static final String CONTENT_TYPE_B_MMS = "application/vnd.wap.mms-message"; 199 public static final String CONTENT_TYPE_B_PUSH_SYNCML_NOTI = "application/vnd.syncml.notification"; 200 201 @UnsupportedAppUsage 202 byte[] mWspData; 203 int mDataLength; 204 long mUnsigned32bit; 205 String mStringValue; 206 207 HashMap<String, String> mContentParameters; 208 209 @UnsupportedAppUsage WspTypeDecoder(byte[] pdu)210 public WspTypeDecoder(byte[] pdu) { 211 mWspData = pdu; 212 } 213 214 /** 215 * Decode the "Text-string" type for WSP pdu 216 * 217 * @param startIndex The starting position of the "Text-string" in this pdu 218 * 219 * @return false when error(not a Text-string) occur 220 * return value can be retrieved by getValueString() method length of data in pdu can be 221 * retrieved by getDecodedDataLength() method 222 */ 223 @UnsupportedAppUsage decodeTextString(int startIndex)224 public boolean decodeTextString(int startIndex) { 225 int index = startIndex; 226 while (mWspData[index] != 0) { 227 index++; 228 } 229 mDataLength = index - startIndex + 1; 230 if (mWspData[startIndex] == 127) { 231 mStringValue = new String(mWspData, startIndex + 1, mDataLength - 2); 232 } else { 233 mStringValue = new String(mWspData, startIndex, mDataLength - 1); 234 } 235 return true; 236 } 237 238 /** 239 * Decode the "Token-text" type for WSP pdu 240 * 241 * @param startIndex The starting position of the "Token-text" in this pdu 242 * 243 * @return always true 244 * return value can be retrieved by getValueString() method 245 * length of data in pdu can be retrieved by getDecodedDataLength() method 246 */ decodeTokenText(int startIndex)247 public boolean decodeTokenText(int startIndex) { 248 int index = startIndex; 249 while (mWspData[index] != 0) { 250 index++; 251 } 252 mDataLength = index - startIndex + 1; 253 mStringValue = new String(mWspData, startIndex, mDataLength - 1); 254 255 return true; 256 } 257 258 /** 259 * Decode the "Short-integer" type for WSP pdu 260 * 261 * @param startIndex The starting position of the "Short-integer" in this pdu 262 * 263 * @return false when error(not a Short-integer) occur 264 * return value can be retrieved by getValue32() method 265 * length of data in pdu can be retrieved by getDecodedDataLength() method 266 */ 267 @UnsupportedAppUsage decodeShortInteger(int startIndex)268 public boolean decodeShortInteger(int startIndex) { 269 if ((mWspData[startIndex] & 0x80) == 0) { 270 return false; 271 } 272 mUnsigned32bit = mWspData[startIndex] & 0x7f; 273 mDataLength = 1; 274 return true; 275 } 276 277 /** 278 * Decode the "Long-integer" type for WSP pdu 279 * 280 * @param startIndex The starting position of the "Long-integer" in this pdu 281 * 282 * @return false when error(not a Long-integer) occur 283 * return value can be retrieved by getValue32() method 284 * length of data in pdu can be retrieved by getDecodedDataLength() method 285 */ decodeLongInteger(int startIndex)286 public boolean decodeLongInteger(int startIndex) { 287 int lengthMultiOctet = mWspData[startIndex] & 0xff; 288 289 if (lengthMultiOctet > WAP_PDU_SHORT_LENGTH_MAX) { 290 return false; 291 } 292 mUnsigned32bit = 0; 293 for (int i = 1; i <= lengthMultiOctet; i++) { 294 mUnsigned32bit = (mUnsigned32bit << 8) | (mWspData[startIndex + i] & 0xff); 295 } 296 mDataLength = 1 + lengthMultiOctet; 297 return true; 298 } 299 300 /** 301 * Decode the "Integer-Value" type for WSP pdu 302 * 303 * @param startIndex The starting position of the "Integer-Value" in this pdu 304 * 305 * @return false when error(not a Integer-Value) occur 306 * return value can be retrieved by getValue32() method 307 * length of data in pdu can be retrieved by getDecodedDataLength() method 308 */ 309 @UnsupportedAppUsage decodeIntegerValue(int startIndex)310 public boolean decodeIntegerValue(int startIndex) { 311 if (decodeShortInteger(startIndex) == true) { 312 return true; 313 } 314 return decodeLongInteger(startIndex); 315 } 316 317 /** 318 * Decode the "Uintvar-integer" type for WSP pdu 319 * 320 * @param startIndex The starting position of the "Uintvar-integer" in this pdu 321 * 322 * @return false when error(not a Uintvar-integer) occur 323 * return value can be retrieved by getValue32() method 324 * length of data in pdu can be retrieved by getDecodedDataLength() method 325 */ 326 @UnsupportedAppUsage decodeUintvarInteger(int startIndex)327 public boolean decodeUintvarInteger(int startIndex) { 328 int index = startIndex; 329 330 mUnsigned32bit = 0; 331 while ((mWspData[index] & 0x80) != 0) { 332 if ((index - startIndex) >= 4) { 333 return false; 334 } 335 mUnsigned32bit = (mUnsigned32bit << 7) | (mWspData[index] & 0x7f); 336 index++; 337 } 338 mUnsigned32bit = (mUnsigned32bit << 7) | (mWspData[index] & 0x7f); 339 mDataLength = index - startIndex + 1; 340 return true; 341 } 342 343 /** 344 * Decode the "Value-length" type for WSP pdu 345 * 346 * @param startIndex The starting position of the "Value-length" in this pdu 347 * 348 * @return false when error(not a Value-length) occur 349 * return value can be retrieved by getValue32() method 350 * length of data in pdu can be retrieved by getDecodedDataLength() method 351 */ 352 @UnsupportedAppUsage decodeValueLength(int startIndex)353 public boolean decodeValueLength(int startIndex) { 354 if ((mWspData[startIndex] & 0xff) > WAP_PDU_LENGTH_QUOTE) { 355 return false; 356 } 357 if (mWspData[startIndex] < WAP_PDU_LENGTH_QUOTE) { 358 mUnsigned32bit = mWspData[startIndex]; 359 mDataLength = 1; 360 } else { 361 decodeUintvarInteger(startIndex + 1); 362 mDataLength++; 363 } 364 return true; 365 } 366 367 /** 368 * Decode the "Extension-media" type for WSP PDU. 369 * 370 * @param startIndex The starting position of the "Extension-media" in this PDU. 371 * 372 * @return false on error, such as if there is no Extension-media at startIndex. 373 * Side-effects: updates stringValue (available with 374 * getValueString()), which will be null on error. The length of the 375 * data in the PDU is available with getValue32(), 0 on error. 376 */ decodeExtensionMedia(int startIndex)377 public boolean decodeExtensionMedia(int startIndex) { 378 int index = startIndex; 379 mDataLength = 0; 380 mStringValue = null; 381 int length = mWspData.length; 382 boolean rtrn = index < length; 383 384 while (index < length && mWspData[index] != 0) { 385 index++; 386 } 387 388 mDataLength = index - startIndex + 1; 389 mStringValue = new String(mWspData, startIndex, mDataLength - 1); 390 391 return rtrn; 392 } 393 394 /** 395 * Decode the "Constrained-encoding" type for WSP pdu 396 * 397 * @param startIndex The starting position of the "Constrained-encoding" in this pdu 398 * 399 * @return false when error(not a Constrained-encoding) occur 400 * return value can be retrieved first by getValueString() and second by getValue32() method 401 * length of data in pdu can be retrieved by getDecodedDataLength() method 402 */ 403 public boolean decodeConstrainedEncoding(int startIndex) { 404 if (decodeShortInteger(startIndex) == true) { 405 mStringValue = null; 406 return true; 407 } 408 return decodeExtensionMedia(startIndex); 409 } 410 411 /** 412 * Decode the "Content-type" type for WSP pdu 413 * 414 * @param startIndex The starting position of the "Content-type" in this pdu 415 * 416 * @return false when error(not a Content-type) occurs 417 * If a content type exists in the headers (either as inline string, or as well-known 418 * value), getValueString() will return it. If a 'well known value' is encountered that 419 * cannot be mapped to a string mime type, getValueString() will return null, and 420 * getValue32() will return the unknown content type value. 421 * length of data in pdu can be retrieved by getDecodedDataLength() method 422 * Any content type parameters will be accessible via getContentParameters() 423 */ 424 @UnsupportedAppUsage 425 public boolean decodeContentType(int startIndex) { 426 int mediaPrefixLength; 427 mContentParameters = new HashMap<String, String>(); 428 429 try { 430 if (decodeValueLength(startIndex) == false) { 431 boolean found = decodeConstrainedEncoding(startIndex); 432 if (found) { 433 expandWellKnownMimeType(); 434 } 435 return found; 436 } 437 int headersLength = (int) mUnsigned32bit; 438 mediaPrefixLength = getDecodedDataLength(); 439 if (decodeIntegerValue(startIndex + mediaPrefixLength) == true) { 440 mDataLength += mediaPrefixLength; 441 int readLength = mDataLength; 442 mStringValue = null; 443 expandWellKnownMimeType(); 444 long wellKnownValue = mUnsigned32bit; 445 String mimeType = mStringValue; 446 if (readContentParameters(startIndex + mDataLength, 447 (headersLength - (mDataLength - mediaPrefixLength)), 0)) { 448 mDataLength += readLength; 449 mUnsigned32bit = wellKnownValue; 450 mStringValue = mimeType; 451 return true; 452 } 453 return false; 454 } 455 if (decodeExtensionMedia(startIndex + mediaPrefixLength) == true) { 456 mDataLength += mediaPrefixLength; 457 int readLength = mDataLength; 458 expandWellKnownMimeType(); 459 long wellKnownValue = mUnsigned32bit; 460 String mimeType = mStringValue; 461 if (readContentParameters(startIndex + mDataLength, 462 (headersLength - (mDataLength - mediaPrefixLength)), 0)) { 463 mDataLength += readLength; 464 mUnsigned32bit = wellKnownValue; 465 mStringValue = mimeType; 466 return true; 467 } 468 } 469 } catch (ArrayIndexOutOfBoundsException e) { 470 //something doesn't add up 471 return false; 472 } 473 return false; 474 } 475 476 private boolean readContentParameters(int startIndex, int leftToRead, int accumulator) { 477 478 int totalRead = 0; 479 480 if (leftToRead > 0) { 481 byte nextByte = mWspData[startIndex]; 482 String value = null; 483 String param = null; 484 if ((nextByte & 0x80) == 0x00 && nextByte > 31) { // untyped 485 decodeTokenText(startIndex); 486 param = mStringValue; 487 totalRead += mDataLength; 488 } else { // typed 489 if (decodeIntegerValue(startIndex)) { 490 totalRead += mDataLength; 491 int wellKnownParameterValue = (int) mUnsigned32bit; 492 param = WELL_KNOWN_PARAMETERS.get(wellKnownParameterValue); 493 if (param == null) { 494 param = "unassigned/0x" + Long.toHexString(wellKnownParameterValue); 495 } 496 // special case for the "Q" parameter, value is a uintvar 497 if (wellKnownParameterValue == Q_VALUE) { 498 if (decodeUintvarInteger(startIndex + totalRead)) { 499 totalRead += mDataLength; 500 value = String.valueOf(mUnsigned32bit); 501 mContentParameters.put(param, value); 502 return readContentParameters(startIndex + totalRead, leftToRead 503 - totalRead, accumulator + totalRead); 504 } else { 505 return false; 506 } 507 } 508 } else { 509 return false; 510 } 511 } 512 513 if (decodeNoValue(startIndex + totalRead)) { 514 totalRead += mDataLength; 515 value = null; 516 } else if (decodeIntegerValue(startIndex + totalRead)) { 517 totalRead += mDataLength; 518 int intValue = (int) mUnsigned32bit; 519 value = String.valueOf(intValue); 520 } else { 521 decodeTokenText(startIndex + totalRead); 522 totalRead += mDataLength; 523 value = mStringValue; 524 if (value.startsWith("\"")) { 525 // quoted string, so remove the quote 526 value = value.substring(1); 527 } 528 } 529 mContentParameters.put(param, value); 530 return readContentParameters(startIndex + totalRead, leftToRead - totalRead, 531 accumulator + totalRead); 532 533 } else { 534 mDataLength = accumulator; 535 return true; 536 } 537 } 538 539 /** 540 * Check if the next byte is No-Value 541 * 542 * @param startIndex The starting position of the "Content length" in this pdu 543 * 544 * @return true if and only if the next byte is 0x00 545 */ decodeNoValue(int startIndex)546 private boolean decodeNoValue(int startIndex) { 547 if (mWspData[startIndex] == 0) { 548 mDataLength = 1; 549 return true; 550 } else { 551 return false; 552 } 553 } 554 555 /** 556 * Populate stringValue with the mime type corresponding to the value in unsigned32bit 557 * 558 * Sets unsigned32bit to -1 if stringValue is already populated 559 */ expandWellKnownMimeType()560 private void expandWellKnownMimeType() { 561 if (mStringValue == null) { 562 int binaryContentType = (int) mUnsigned32bit; 563 mStringValue = WELL_KNOWN_MIME_TYPES.get(binaryContentType); 564 } else { 565 mUnsigned32bit = -1; 566 } 567 } 568 569 /** 570 * Decode the "Content length" type for WSP pdu 571 * 572 * @param startIndex The starting position of the "Content length" in this pdu 573 * 574 * @return false when error(not a Content length) occur 575 * return value can be retrieved by getValue32() method 576 * length of data in pdu can be retrieved by getDecodedDataLength() method 577 */ decodeContentLength(int startIndex)578 public boolean decodeContentLength(int startIndex) { 579 return decodeIntegerValue(startIndex); 580 } 581 582 /** 583 * Decode the "Content location" type for WSP pdu 584 * 585 * @param startIndex The starting position of the "Content location" in this pdu 586 * 587 * @return false when error(not a Content location) occur 588 * return value can be retrieved by getValueString() method 589 * length of data in pdu can be retrieved by getDecodedDataLength() method 590 */ decodeContentLocation(int startIndex)591 public boolean decodeContentLocation(int startIndex) { 592 return decodeTextString(startIndex); 593 } 594 595 /** 596 * Decode the "X-Wap-Application-Id" type for WSP pdu 597 * 598 * @param startIndex The starting position of the "X-Wap-Application-Id" in this pdu 599 * 600 * @return false when error(not a X-Wap-Application-Id) occur 601 * return value can be retrieved first by getValueString() and second by getValue32() 602 * method 603 * length of data in pdu can be retrieved by getDecodedDataLength() method 604 */ 605 @UnsupportedAppUsage decodeXWapApplicationId(int startIndex)606 public boolean decodeXWapApplicationId(int startIndex) { 607 if (decodeIntegerValue(startIndex) == true) { 608 mStringValue = null; 609 return true; 610 } 611 return decodeTextString(startIndex); 612 } 613 614 /** 615 * Seek for the "X-Wap-Application-Id" field for WSP pdu 616 * 617 * @param startIndex The starting position of seek pointer 618 * @param endIndex Valid seek area end point 619 * 620 * @return false when error(not a X-Wap-Application-Id) occur 621 * return value can be retrieved by getValue32() 622 */ 623 @UnsupportedAppUsage seekXWapApplicationId(int startIndex, int endIndex)624 public boolean seekXWapApplicationId(int startIndex, int endIndex) { 625 int index = startIndex; 626 627 try { 628 for (index = startIndex; index <= endIndex; ) { 629 /** 630 * 8.4.1.1 Field name 631 * Field name is integer or text. 632 */ 633 if (decodeIntegerValue(index)) { 634 int fieldValue = (int) getValue32(); 635 636 if (fieldValue == PARAMETER_ID_X_WAP_APPLICATION_ID) { 637 mUnsigned32bit = index + 1; 638 return true; 639 } 640 } else { 641 if (!decodeTextString(index)) return false; 642 } 643 index += getDecodedDataLength(); 644 if (index > endIndex) return false; 645 646 /** 647 * 8.4.1.2 Field values 648 * Value Interpretation of First Octet 649 * 0 - 30 This octet is followed by the indicated number (0 - 30) 650 of data octets 651 * 31 This octet is followed by a uintvar, which indicates the number 652 * of data octets after it 653 * 32 - 127 The value is a text string, terminated by a zero octet 654 (NUL character) 655 * 128 - 255 It is an encoded 7-bit value; this header has no more data 656 */ 657 byte val = mWspData[index]; 658 if (0 <= val && val <= WAP_PDU_SHORT_LENGTH_MAX) { 659 index += mWspData[index] + 1; 660 } else if (val == WAP_PDU_LENGTH_QUOTE) { 661 if (index + 1 >= endIndex) return false; 662 index++; 663 if (!decodeUintvarInteger(index)) return false; 664 index += getDecodedDataLength(); 665 } else if (WAP_PDU_LENGTH_QUOTE < val && val <= 127) { 666 if (!decodeTextString(index)) return false; 667 index += getDecodedDataLength(); 668 } else { 669 index++; 670 } 671 } 672 } catch (ArrayIndexOutOfBoundsException e) { 673 //seek application ID failed. WSP header might be corrupted 674 return false; 675 } 676 return false; 677 } 678 679 /** 680 * Decode the "X-Wap-Content-URI" type for WSP pdu 681 * 682 * @param startIndex The starting position of the "X-Wap-Content-URI" in this pdu 683 * 684 * @return false when error(not a X-Wap-Content-URI) occur 685 * return value can be retrieved by getValueString() method 686 * length of data in pdu can be retrieved by getDecodedDataLength() method 687 */ decodeXWapContentURI(int startIndex)688 public boolean decodeXWapContentURI(int startIndex) { 689 return decodeTextString(startIndex); 690 } 691 692 /** 693 * Decode the "X-Wap-Initiator-URI" type for WSP pdu 694 * 695 * @param startIndex The starting position of the "X-Wap-Initiator-URI" in this pdu 696 * 697 * @return false when error(not a X-Wap-Initiator-URI) occur 698 * return value can be retrieved by getValueString() method 699 * length of data in pdu can be retrieved by getDecodedDataLength() method 700 */ decodeXWapInitiatorURI(int startIndex)701 public boolean decodeXWapInitiatorURI(int startIndex) { 702 return decodeTextString(startIndex); 703 } 704 705 /** 706 * The data length of latest operation. 707 */ 708 @UnsupportedAppUsage getDecodedDataLength()709 public int getDecodedDataLength() { 710 return mDataLength; 711 } 712 713 /** 714 * The 32-bits result of latest operation. 715 */ 716 @UnsupportedAppUsage getValue32()717 public long getValue32() { 718 return mUnsigned32bit; 719 } 720 721 /** 722 * The String result of latest operation. 723 */ 724 @UnsupportedAppUsage getValueString()725 public String getValueString() { 726 return mStringValue; 727 } 728 729 /** 730 * Any parameters encountered as part of a decodeContentType() invocation. 731 * 732 * @return a map of content parameters keyed by their names, or null if 733 * decodeContentType() has not been called If any unassigned 734 * well-known parameters are encountered, the key of the map will be 735 * 'unassigned/0x...', where '...' is the hex value of the 736 * unassigned parameter. If a parameter has No-Value the value will be null. 737 * 738 */ 739 @UnsupportedAppUsage getContentParameters()740 public HashMap<String, String> getContentParameters() { 741 return mContentParameters; 742 } 743 } 744