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