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