/** Append header to mMessage. */ private int appendHeader(int field) { switch (field) { case PduHeaders.MMS_VERSION: appendOctet(field); int version = mPduHeader.getOctet(field); if (0 == version) { appendShortInteger(PduHeaders.CURRENT_MMS_VERSION); } else { appendShortInteger(version); } break; case PduHeaders.MESSAGE_ID: case PduHeaders.TRANSACTION_ID: byte[] textString = mPduHeader.getTextString(field); if (null == textString) { return PDU_COMPOSE_FIELD_NOT_SET; } appendOctet(field); appendTextString(textString); break; case PduHeaders.TO: case PduHeaders.BCC: case PduHeaders.CC: EncodedStringValue[] addr = mPduHeader.getEncodedStringValues(field); if (null == addr) { return PDU_COMPOSE_FIELD_NOT_SET; } EncodedStringValue temp; for (int i = 0; i < addr.length; i++) { temp = appendAddressType(addr[i]); if (temp == null) { return PDU_COMPOSE_CONTENT_ERROR; } appendOctet(field); appendEncodedString(temp); } break; case PduHeaders.FROM: // Value-length (Address-present-token Encoded-string-value | Insert-address-token) appendOctet(field); EncodedStringValue from = mPduHeader.getEncodedStringValue(field); if ((from == null) || TextUtils.isEmpty(from.getString()) || new String(from.getTextString()).equals(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR)) { // Length of from = 1 append(1); // Insert-address-token = <Octet 129> append(PduHeaders.FROM_INSERT_ADDRESS_TOKEN); } else { mStack.newbuf(); PositionMarker fstart = mStack.mark(); // Address-present-token = <Octet 128> append(PduHeaders.FROM_ADDRESS_PRESENT_TOKEN); temp = appendAddressType(from); if (temp == null) { return PDU_COMPOSE_CONTENT_ERROR; } appendEncodedString(temp); int flen = fstart.getLength(); mStack.pop(); appendValueLength(flen); mStack.copy(); } break; case PduHeaders.READ_STATUS: case PduHeaders.STATUS: case PduHeaders.REPORT_ALLOWED: case PduHeaders.PRIORITY: case PduHeaders.DELIVERY_REPORT: case PduHeaders.READ_REPORT: int octet = mPduHeader.getOctet(field); if (0 == octet) { return PDU_COMPOSE_FIELD_NOT_SET; } appendOctet(field); appendOctet(octet); break; case PduHeaders.DATE: long date = mPduHeader.getLongInteger(field); if (-1 == date) { return PDU_COMPOSE_FIELD_NOT_SET; } appendOctet(field); appendDateValue(date); break; case PduHeaders.SUBJECT: EncodedStringValue enString = mPduHeader.getEncodedStringValue(field); if (null == enString) { return PDU_COMPOSE_FIELD_NOT_SET; } appendOctet(field); appendEncodedString(enString); break; case PduHeaders.MESSAGE_CLASS: byte[] messageClass = mPduHeader.getTextString(field); if (null == messageClass) { return PDU_COMPOSE_FIELD_NOT_SET; } appendOctet(field); if (Arrays.equals(messageClass, PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes())) { appendOctet(PduHeaders.MESSAGE_CLASS_ADVERTISEMENT); } else if (Arrays.equals(messageClass, PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes())) { appendOctet(PduHeaders.MESSAGE_CLASS_AUTO); } else if (Arrays.equals(messageClass, PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes())) { appendOctet(PduHeaders.MESSAGE_CLASS_PERSONAL); } else if (Arrays.equals( messageClass, PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes())) { appendOctet(PduHeaders.MESSAGE_CLASS_INFORMATIONAL); } else { appendTextString(messageClass); } break; case PduHeaders.EXPIRY: long expiry = mPduHeader.getLongInteger(field); if (-1 == expiry) { return PDU_COMPOSE_FIELD_NOT_SET; } appendOctet(field); mStack.newbuf(); PositionMarker expiryStart = mStack.mark(); append(PduHeaders.VALUE_RELATIVE_TOKEN); appendLongInteger(expiry); int expiryLength = expiryStart.getLength(); mStack.pop(); appendValueLength(expiryLength); mStack.copy(); break; default: return PDU_COMPOSE_FIELD_NOT_SUPPORTED; } return PDU_COMPOSE_SUCCESS; }
/** * Parse pdu headers. * * @param pduDataStream pdu data input stream * @return headers in PduHeaders structure, null when parse fail */ protected PduHeaders parseHeaders(ByteArrayInputStream pduDataStream) { if (pduDataStream == null) { return null; } boolean keepParsing = true; PduHeaders headers = new PduHeaders(); while (keepParsing && (pduDataStream.available() > 0)) { int headerField = extractByteValue(pduDataStream); switch (headerField) { case PduHeaders.MESSAGE_TYPE: { int messageType = extractByteValue(pduDataStream); switch (messageType) { // We don't support these kind of messages now. case PduHeaders.MESSAGE_TYPE_FORWARD_REQ: case PduHeaders.MESSAGE_TYPE_FORWARD_CONF: case PduHeaders.MESSAGE_TYPE_MBOX_STORE_REQ: case PduHeaders.MESSAGE_TYPE_MBOX_STORE_CONF: case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_REQ: case PduHeaders.MESSAGE_TYPE_MBOX_VIEW_CONF: case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_REQ: case PduHeaders.MESSAGE_TYPE_MBOX_UPLOAD_CONF: case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_REQ: case PduHeaders.MESSAGE_TYPE_MBOX_DELETE_CONF: case PduHeaders.MESSAGE_TYPE_MBOX_DESCR: case PduHeaders.MESSAGE_TYPE_DELETE_REQ: case PduHeaders.MESSAGE_TYPE_DELETE_CONF: case PduHeaders.MESSAGE_TYPE_CANCEL_REQ: case PduHeaders.MESSAGE_TYPE_CANCEL_CONF: return null; } try { headers.setOctet(messageType, headerField); } catch (IllegalArgumentException e) { log( "Set invalid Octet value: " + messageType + " into the header filed: " + headerField); return null; } catch (RuntimeException e) { log(headerField + "is not Octet header field!"); return null; } break; } /* Octect value */ case PduHeaders.REPORT_ALLOWED: case PduHeaders.ADAPTATION_ALLOWED: case PduHeaders.DELIVERY_REPORT: case PduHeaders.DRM_CONTENT: case PduHeaders.DISTRIBUTION_INDICATOR: case PduHeaders.QUOTAS: case PduHeaders.READ_REPORT: case PduHeaders.STORE: case PduHeaders.STORED: case PduHeaders.TOTALS: case PduHeaders.SENDER_VISIBILITY: case PduHeaders.READ_STATUS: case PduHeaders.CANCEL_STATUS: case PduHeaders.PRIORITY: case PduHeaders.STATUS: case PduHeaders.REPLY_CHARGING: case PduHeaders.MM_STATE: case PduHeaders.RECOMMENDED_RETRIEVAL_MODE: case PduHeaders.CONTENT_CLASS: case PduHeaders.RETRIEVE_STATUS: case PduHeaders.STORE_STATUS: /** * The following field has a different value when used in the M-Mbox-Delete.conf and * M-Delete.conf PDU. For now we ignore this fact, since we do not support these PDUs */ case PduHeaders.RESPONSE_STATUS: { int value = extractByteValue(pduDataStream); try { headers.setOctet(value, headerField); } catch (IllegalArgumentException e) { log("Set invalid Octet value: " + value + " into the header filed: " + headerField); return null; } catch (RuntimeException e) { log(headerField + "is not Octet header field!"); return null; } break; } /* Long-Integer */ case PduHeaders.DATE: case PduHeaders.REPLY_CHARGING_SIZE: case PduHeaders.MESSAGE_SIZE: { try { long value = parseLongInteger(pduDataStream); headers.setLongInteger(value, headerField); } catch (RuntimeException e) { log(headerField + "is not Long-Integer header field!"); return null; } break; } /* Integer-Value */ case PduHeaders.MESSAGE_COUNT: case PduHeaders.START: case PduHeaders.LIMIT: { try { long value = parseIntegerValue(pduDataStream); headers.setLongInteger(value, headerField); } catch (RuntimeException e) { log(headerField + "is not Long-Integer header field!"); return null; } break; } /* Text-String */ case PduHeaders.TRANSACTION_ID: case PduHeaders.REPLY_CHARGING_ID: case PduHeaders.AUX_APPLIC_ID: case PduHeaders.APPLIC_ID: case PduHeaders.REPLY_APPLIC_ID: /** * The next three header fields are email addresses as defined in RFC2822, not including * the characters "<" and ">" */ case PduHeaders.MESSAGE_ID: case PduHeaders.REPLACE_ID: case PduHeaders.CANCEL_ID: /** * The following field has a different value when used in the M-Mbox-Delete.conf and * M-Delete.conf PDU. For now we ignore this fact, since we do not support these PDUs */ case PduHeaders.CONTENT_LOCATION: { byte[] value = parseWapString(pduDataStream, TYPE_TEXT_STRING); if (null != value) { try { headers.setTextString(value, headerField); } catch (NullPointerException e) { log("null pointer error!"); } catch (RuntimeException e) { log(headerField + "is not Text-String header field!"); return null; } } break; } /* Encoded-string-value */ case PduHeaders.SUBJECT: case PduHeaders.RECOMMENDED_RETRIEVAL_MODE_TEXT: case PduHeaders.RETRIEVE_TEXT: case PduHeaders.STATUS_TEXT: case PduHeaders.STORE_STATUS_TEXT: /* the next one is not support * M-Mbox-Delete.conf and M-Delete.conf now */ case PduHeaders.RESPONSE_TEXT: { EncodedStringValue value = parseEncodedStringValue(pduDataStream); if (null != value) { try { headers.setEncodedStringValue(value, headerField); } catch (NullPointerException e) { log("null pointer error!"); } catch (RuntimeException e) { log(headerField + "is not Encoded-String-Value header field!"); return null; } } break; } /* Addressing model */ case PduHeaders.BCC: case PduHeaders.CC: case PduHeaders.TO: { EncodedStringValue value = parseEncodedStringValue(pduDataStream); if (null != value) { byte[] address = value.getTextString(); if (null != address) { String str = new String(address); int endIndex = str.indexOf("/"); if (endIndex > 0) { str = str.substring(0, endIndex); } try { value.setTextString(str.getBytes()); } catch (NullPointerException e) { log("null pointer error!"); return null; } } try { headers.appendEncodedStringValue(value, headerField); } catch (NullPointerException e) { log("null pointer error!"); } catch (RuntimeException e) { log(headerField + "is not Encoded-String-Value header field!"); return null; } } break; } /* Value-length * (Absolute-token Date-value | Relative-token Delta-seconds-value) */ case PduHeaders.DELIVERY_TIME: case PduHeaders.EXPIRY: case PduHeaders.REPLY_CHARGING_DEADLINE: { /* parse Value-length */ parseValueLength(pduDataStream); /* Absolute-token or Relative-token */ int token = extractByteValue(pduDataStream); /* Date-value or Delta-seconds-value */ long timeValue; try { timeValue = parseLongInteger(pduDataStream); } catch (RuntimeException e) { log(headerField + "is not Long-Integer header field!"); return null; } if (PduHeaders.VALUE_RELATIVE_TOKEN == token) { /* need to convert the Delta-seconds-value * into Date-value */ timeValue = System.currentTimeMillis() / 1000 + timeValue; } try { headers.setLongInteger(timeValue, headerField); } catch (RuntimeException e) { log(headerField + "is not Long-Integer header field!"); return null; } break; } case PduHeaders.FROM: { /* From-value = * Value-length * (Address-present-token Encoded-string-value | Insert-address-token) */ EncodedStringValue from = null; parseValueLength(pduDataStream); /* parse value-length */ /* Address-present-token or Insert-address-token */ int fromToken = extractByteValue(pduDataStream); /* Address-present-token or Insert-address-token */ if (PduHeaders.FROM_ADDRESS_PRESENT_TOKEN == fromToken) { /* Encoded-string-value */ from = parseEncodedStringValue(pduDataStream); if (null != from) { byte[] address = from.getTextString(); if (null != address) { String str = new String(address); int endIndex = str.indexOf("/"); if (endIndex > 0) { str = str.substring(0, endIndex); } try { from.setTextString(str.getBytes()); } catch (NullPointerException e) { log("null pointer error!"); return null; } } } } else { try { from = new EncodedStringValue(PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.getBytes()); } catch (NullPointerException e) { log(headerField + "is not Encoded-String-Value header field!"); return null; } } try { headers.setEncodedStringValue(from, PduHeaders.FROM); } catch (NullPointerException e) { log("null pointer error!"); } catch (RuntimeException e) { log(headerField + "is not Encoded-String-Value header field!"); return null; } break; } case PduHeaders.MESSAGE_CLASS: { /* Message-class-value = Class-identifier | Token-text */ pduDataStream.mark(1); int messageClass = extractByteValue(pduDataStream); if (messageClass >= PduHeaders.MESSAGE_CLASS_PERSONAL) { /* Class-identifier */ try { if (PduHeaders.MESSAGE_CLASS_PERSONAL == messageClass) { headers.setTextString( PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes(), PduHeaders.MESSAGE_CLASS); } else if (PduHeaders.MESSAGE_CLASS_ADVERTISEMENT == messageClass) { headers.setTextString( PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes(), PduHeaders.MESSAGE_CLASS); } else if (PduHeaders.MESSAGE_CLASS_INFORMATIONAL == messageClass) { headers.setTextString( PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes(), PduHeaders.MESSAGE_CLASS); } else if (PduHeaders.MESSAGE_CLASS_AUTO == messageClass) { headers.setTextString( PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes(), PduHeaders.MESSAGE_CLASS); } } catch (NullPointerException e) { log("null pointer error!"); } catch (RuntimeException e) { log(headerField + "is not Text-String header field!"); return null; } } else { /* Token-text */ pduDataStream.reset(); byte[] messageClassString = parseWapString(pduDataStream, TYPE_TEXT_STRING); if (null != messageClassString) { try { headers.setTextString(messageClassString, PduHeaders.MESSAGE_CLASS); } catch (NullPointerException e) { log("null pointer error!"); } catch (RuntimeException e) { log(headerField + "is not Text-String header field!"); return null; } } } break; } case PduHeaders.MMS_VERSION: { int version = parseShortInteger(pduDataStream); try { headers.setOctet(version, PduHeaders.MMS_VERSION); } catch (IllegalArgumentException e) { log("Set invalid Octet value: " + version + " into the header filed: " + headerField); return null; } catch (RuntimeException e) { log(headerField + "is not Octet header field!"); return null; } break; } case PduHeaders.PREVIOUSLY_SENT_BY: { /* Previously-sent-by-value = * Value-length Forwarded-count-value Encoded-string-value */ /* parse value-length */ parseValueLength(pduDataStream); /* parse Forwarded-count-value */ try { parseIntegerValue(pduDataStream); } catch (RuntimeException e) { log(headerField + " is not Integer-Value"); return null; } /* parse Encoded-string-value */ EncodedStringValue previouslySentBy = parseEncodedStringValue(pduDataStream); if (null != previouslySentBy) { try { headers.setEncodedStringValue(previouslySentBy, PduHeaders.PREVIOUSLY_SENT_BY); } catch (NullPointerException e) { log("null pointer error!"); } catch (RuntimeException e) { log(headerField + "is not Encoded-String-Value header field!"); return null; } } break; } case PduHeaders.PREVIOUSLY_SENT_DATE: { /* Previously-sent-date-value = * Value-length Forwarded-count-value Date-value */ /* parse value-length */ parseValueLength(pduDataStream); /* parse Forwarded-count-value */ try { parseIntegerValue(pduDataStream); } catch (RuntimeException e) { log(headerField + " is not Integer-Value"); return null; } /* Date-value */ try { long perviouslySentDate = parseLongInteger(pduDataStream); headers.setLongInteger(perviouslySentDate, PduHeaders.PREVIOUSLY_SENT_DATE); } catch (RuntimeException e) { log(headerField + "is not Long-Integer header field!"); return null; } break; } case PduHeaders.MM_FLAGS: { /* MM-flags-value = * Value-length * ( Add-token | Remove-token | Filter-token ) * Encoded-string-value */ /* parse Value-length */ parseValueLength(pduDataStream); /* Add-token | Remove-token | Filter-token */ extractByteValue(pduDataStream); /* Encoded-string-value */ parseEncodedStringValue(pduDataStream); /* not store this header filed in "headers", * because now PduHeaders doesn't support it */ break; } /* Value-length * (Message-total-token | Size-total-token) Integer-Value */ case PduHeaders.MBOX_TOTALS: case PduHeaders.MBOX_QUOTAS: { /* Value-length */ parseValueLength(pduDataStream); /* Message-total-token | Size-total-token */ extractByteValue(pduDataStream); /*Integer-Value*/ try { parseIntegerValue(pduDataStream); } catch (RuntimeException e) { log(headerField + " is not Integer-Value"); return null; } /* not store these headers filed in "headers", because now PduHeaders doesn't support them */ break; } case PduHeaders.ELEMENT_DESCRIPTOR: { parseContentType(pduDataStream, null); /* not store this header filed in "headers", because now PduHeaders doesn't support it */ break; } case PduHeaders.CONTENT_TYPE: { HashMap<Integer, Object> map = new HashMap<Integer, Object>(); byte[] contentType = parseContentType(pduDataStream, map); if (null != contentType) { try { headers.setTextString(contentType, PduHeaders.CONTENT_TYPE); } catch (NullPointerException e) { log("null pointer error!"); } catch (RuntimeException e) { log(headerField + "is not Text-String header field!"); return null; } } keepParsing = false; break; } case PduHeaders.CONTENT: case PduHeaders.ADDITIONAL_HEADERS: case PduHeaders.ATTRIBUTES: default: { log("Unknown header"); } } } return headers; }