mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-20 06:28:27 +00:00
Updated PDU processing code.
The code we use for PDU parsing and composing comes straight from the Android framework, but it's an internal API, so we duplicate the code here. These changes represent updates that have been made as of the JB release.
This commit is contained in:
parent
7beb8e489b
commit
2c82e7b343
@ -26,6 +26,7 @@ public class ContentType {
|
|||||||
public static final String MMS_GENERIC = "application/vnd.wap.mms-generic";
|
public static final String MMS_GENERIC = "application/vnd.wap.mms-generic";
|
||||||
public static final String MULTIPART_MIXED = "application/vnd.wap.multipart.mixed";
|
public static final String MULTIPART_MIXED = "application/vnd.wap.multipart.mixed";
|
||||||
public static final String MULTIPART_RELATED = "application/vnd.wap.multipart.related";
|
public static final String MULTIPART_RELATED = "application/vnd.wap.multipart.related";
|
||||||
|
public static final String MULTIPART_ALTERNATIVE = "application/vnd.wap.multipart.alternative";
|
||||||
|
|
||||||
public static final String TEXT_PLAIN = "text/plain";
|
public static final String TEXT_PLAIN = "text/plain";
|
||||||
public static final String TEXT_HTML = "text/html";
|
public static final String TEXT_HTML = "text/html";
|
||||||
@ -38,6 +39,7 @@ public class ContentType {
|
|||||||
public static final String IMAGE_GIF = "image/gif";
|
public static final String IMAGE_GIF = "image/gif";
|
||||||
public static final String IMAGE_WBMP = "image/vnd.wap.wbmp";
|
public static final String IMAGE_WBMP = "image/vnd.wap.wbmp";
|
||||||
public static final String IMAGE_PNG = "image/png";
|
public static final String IMAGE_PNG = "image/png";
|
||||||
|
public static final String IMAGE_X_MS_BMP = "image/x-ms-bmp";
|
||||||
|
|
||||||
public static final String AUDIO_UNSPECIFIED = "audio/*";
|
public static final String AUDIO_UNSPECIFIED = "audio/*";
|
||||||
public static final String AUDIO_AAC = "audio/aac";
|
public static final String AUDIO_AAC = "audio/aac";
|
||||||
@ -57,6 +59,7 @@ public class ContentType {
|
|||||||
public static final String AUDIO_X_MPEG = "audio/x-mpeg";
|
public static final String AUDIO_X_MPEG = "audio/x-mpeg";
|
||||||
public static final String AUDIO_X_MPG = "audio/x-mpg";
|
public static final String AUDIO_X_MPG = "audio/x-mpg";
|
||||||
public static final String AUDIO_3GPP = "audio/3gpp";
|
public static final String AUDIO_3GPP = "audio/3gpp";
|
||||||
|
public static final String AUDIO_X_WAV = "audio/x-wav";
|
||||||
public static final String AUDIO_OGG = "application/ogg";
|
public static final String AUDIO_OGG = "application/ogg";
|
||||||
|
|
||||||
public static final String VIDEO_UNSPECIFIED = "video/*";
|
public static final String VIDEO_UNSPECIFIED = "video/*";
|
||||||
@ -88,6 +91,7 @@ public class ContentType {
|
|||||||
sSupportedContentTypes.add(IMAGE_WBMP);
|
sSupportedContentTypes.add(IMAGE_WBMP);
|
||||||
sSupportedContentTypes.add(IMAGE_PNG);
|
sSupportedContentTypes.add(IMAGE_PNG);
|
||||||
sSupportedContentTypes.add(IMAGE_JPG);
|
sSupportedContentTypes.add(IMAGE_JPG);
|
||||||
|
sSupportedContentTypes.add(IMAGE_X_MS_BMP);
|
||||||
//supportedContentTypes.add(IMAGE_SVG); not yet supported.
|
//supportedContentTypes.add(IMAGE_SVG); not yet supported.
|
||||||
|
|
||||||
sSupportedContentTypes.add(AUDIO_AAC);
|
sSupportedContentTypes.add(AUDIO_AAC);
|
||||||
@ -105,6 +109,7 @@ public class ContentType {
|
|||||||
sSupportedContentTypes.add(AUDIO_X_MPEG3);
|
sSupportedContentTypes.add(AUDIO_X_MPEG3);
|
||||||
sSupportedContentTypes.add(AUDIO_X_MPEG);
|
sSupportedContentTypes.add(AUDIO_X_MPEG);
|
||||||
sSupportedContentTypes.add(AUDIO_X_MPG);
|
sSupportedContentTypes.add(AUDIO_X_MPG);
|
||||||
|
sSupportedContentTypes.add(AUDIO_X_WAV);
|
||||||
sSupportedContentTypes.add(AUDIO_3GPP);
|
sSupportedContentTypes.add(AUDIO_3GPP);
|
||||||
sSupportedContentTypes.add(AUDIO_OGG);
|
sSupportedContentTypes.add(AUDIO_OGG);
|
||||||
|
|
||||||
@ -126,6 +131,7 @@ public class ContentType {
|
|||||||
sSupportedImageTypes.add(IMAGE_WBMP);
|
sSupportedImageTypes.add(IMAGE_WBMP);
|
||||||
sSupportedImageTypes.add(IMAGE_PNG);
|
sSupportedImageTypes.add(IMAGE_PNG);
|
||||||
sSupportedImageTypes.add(IMAGE_JPG);
|
sSupportedImageTypes.add(IMAGE_JPG);
|
||||||
|
sSupportedImageTypes.add(IMAGE_X_MS_BMP);
|
||||||
|
|
||||||
// add supported audio types
|
// add supported audio types
|
||||||
sSupportedAudioTypes.add(AUDIO_AAC);
|
sSupportedAudioTypes.add(AUDIO_AAC);
|
||||||
@ -144,6 +150,7 @@ public class ContentType {
|
|||||||
sSupportedAudioTypes.add(AUDIO_X_MPEG3);
|
sSupportedAudioTypes.add(AUDIO_X_MPEG3);
|
||||||
sSupportedAudioTypes.add(AUDIO_X_MPEG);
|
sSupportedAudioTypes.add(AUDIO_X_MPEG);
|
||||||
sSupportedAudioTypes.add(AUDIO_X_MPG);
|
sSupportedAudioTypes.add(AUDIO_X_MPG);
|
||||||
|
sSupportedAudioTypes.add(AUDIO_X_WAV);
|
||||||
sSupportedAudioTypes.add(AUDIO_3GPP);
|
sSupportedAudioTypes.add(AUDIO_3GPP);
|
||||||
sSupportedAudioTypes.add(AUDIO_OGG);
|
sSupportedAudioTypes.add(AUDIO_OGG);
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ package ws.com.google.android.mms.pdu;
|
|||||||
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -177,7 +177,7 @@ public class PduComposer {
|
|||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.w("PduComposer", "Returning: " + mMessage.size() + " bytes...");
|
Log.w("PduComposer", "Returning: " + mMessage.size() + " bytes...");
|
||||||
|
|
||||||
return mMessage.toByteArray();
|
return mMessage.toByteArray();
|
||||||
@ -761,7 +761,7 @@ public class PduComposer {
|
|||||||
*/
|
*/
|
||||||
private int makeSendReqPdu() {
|
private int makeSendReqPdu() {
|
||||||
Log.w("PduComposer", "Making send request...");
|
Log.w("PduComposer", "Making send request...");
|
||||||
|
|
||||||
if (mMessage == null) {
|
if (mMessage == null) {
|
||||||
mMessage = new ByteArrayOutputStream();
|
mMessage = new ByteArrayOutputStream();
|
||||||
mPosition = 0;
|
mPosition = 0;
|
||||||
@ -839,11 +839,7 @@ public class PduComposer {
|
|||||||
appendOctet(PduHeaders.CONTENT_TYPE);
|
appendOctet(PduHeaders.CONTENT_TYPE);
|
||||||
|
|
||||||
// Message body
|
// Message body
|
||||||
makeMessageBody();
|
return makeMessageBody();
|
||||||
|
|
||||||
Log.w("PduComposer", "Returning success...");
|
|
||||||
|
|
||||||
return PDU_COMPOSE_SUCCESS; // Composing the message is OK
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
|
|
||||||
package ws.com.google.android.mms.pdu;
|
package ws.com.google.android.mms.pdu;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import ws.com.google.android.mms.ContentType;
|
import ws.com.google.android.mms.ContentType;
|
||||||
import ws.com.google.android.mms.InvalidHeaderValueException;
|
import ws.com.google.android.mms.InvalidHeaderValueException;
|
||||||
|
|
||||||
import android.util.Config;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
@ -84,7 +84,7 @@ public class PduParser {
|
|||||||
*/
|
*/
|
||||||
private static final String LOG_TAG = "PduParser";
|
private static final String LOG_TAG = "PduParser";
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
|
private static final boolean LOCAL_LOGV = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -102,6 +102,7 @@ public class PduParser {
|
|||||||
* null if parsing error happened or mandatory fields are not set.
|
* null if parsing error happened or mandatory fields are not set.
|
||||||
*/
|
*/
|
||||||
public GenericPdu parse(){
|
public GenericPdu parse(){
|
||||||
|
Log.w("PduParser", "parse() called...");
|
||||||
if (mPduDataStream == null) {
|
if (mPduDataStream == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -122,9 +123,11 @@ public class PduParser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.w("PduParser", "Message Type: " + messageType);
|
||||||
if ((PduHeaders.MESSAGE_TYPE_SEND_REQ == messageType) ||
|
if ((PduHeaders.MESSAGE_TYPE_SEND_REQ == messageType) ||
|
||||||
(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF == messageType)) {
|
(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF == messageType)) {
|
||||||
/* need to parse the parts */
|
/* need to parse the parts */
|
||||||
|
Log.w("PduParser", "Parsing parts...");
|
||||||
mBody = parseParts(mPduDataStream);
|
mBody = parseParts(mPduDataStream);
|
||||||
if (null == mBody) {
|
if (null == mBody) {
|
||||||
// Parse parts failed.
|
// Parse parts failed.
|
||||||
@ -157,9 +160,18 @@ public class PduParser {
|
|||||||
}
|
}
|
||||||
String ctTypeStr = new String(contentType);
|
String ctTypeStr = new String(contentType);
|
||||||
if (ctTypeStr.equals(ContentType.MULTIPART_MIXED)
|
if (ctTypeStr.equals(ContentType.MULTIPART_MIXED)
|
||||||
|| ctTypeStr.equals(ContentType.MULTIPART_RELATED)) {
|
|| ctTypeStr.equals(ContentType.MULTIPART_RELATED)
|
||||||
|
|| ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
|
||||||
// The MMS content type must be "application/vnd.wap.multipart.mixed"
|
// The MMS content type must be "application/vnd.wap.multipart.mixed"
|
||||||
// or "application/vnd.wap.multipart.related"
|
// or "application/vnd.wap.multipart.related"
|
||||||
|
// or "application/vnd.wap.multipart.alternative"
|
||||||
|
return retrieveConf;
|
||||||
|
} else if (ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
|
||||||
|
// "application/vnd.wap.multipart.alternative"
|
||||||
|
// should take only the first part.
|
||||||
|
PduPart firstPart = mBody.getPart(0);
|
||||||
|
mBody.removeAll();
|
||||||
|
mBody.addPart(0, firstPart);
|
||||||
return retrieveConf;
|
return retrieveConf;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -200,7 +212,18 @@ public class PduParser {
|
|||||||
PduHeaders headers = new PduHeaders();
|
PduHeaders headers = new PduHeaders();
|
||||||
|
|
||||||
while (keepParsing && (pduDataStream.available() > 0)) {
|
while (keepParsing && (pduDataStream.available() > 0)) {
|
||||||
|
pduDataStream.mark(1);
|
||||||
int headerField = extractByteValue(pduDataStream);
|
int headerField = extractByteValue(pduDataStream);
|
||||||
|
/* parse custom text header */
|
||||||
|
if ((headerField >= TEXT_MIN) && (headerField <= TEXT_MAX)) {
|
||||||
|
pduDataStream.reset();
|
||||||
|
byte [] bVal = parseWapString(pduDataStream, TYPE_TEXT_STRING);
|
||||||
|
if (LOCAL_LOGV) {
|
||||||
|
Log.v(LOG_TAG, "TextHeader: " + new String(bVal));
|
||||||
|
}
|
||||||
|
/* we should ignore it at the moment */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
switch (headerField) {
|
switch (headerField) {
|
||||||
case PduHeaders.MESSAGE_TYPE:
|
case PduHeaders.MESSAGE_TYPE:
|
||||||
{
|
{
|
||||||
@ -778,26 +801,34 @@ public class PduParser {
|
|||||||
/* get part's data */
|
/* get part's data */
|
||||||
if (dataLength > 0) {
|
if (dataLength > 0) {
|
||||||
byte[] partData = new byte[dataLength];
|
byte[] partData = new byte[dataLength];
|
||||||
|
String partContentType = new String(part.getContentType());
|
||||||
pduDataStream.read(partData, 0, dataLength);
|
pduDataStream.read(partData, 0, dataLength);
|
||||||
// Check Content-Transfer-Encoding.
|
if (partContentType.equalsIgnoreCase(ContentType.MULTIPART_ALTERNATIVE)) {
|
||||||
byte[] partDataEncoding = part.getContentTransferEncoding();
|
// parse "multipart/vnd.wap.multipart.alternative".
|
||||||
if (null != partDataEncoding) {
|
PduBody childBody = parseParts(new ByteArrayInputStream(partData));
|
||||||
String encoding = new String(partDataEncoding);
|
// take the first part of children.
|
||||||
if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) {
|
part = childBody.getPart(0);
|
||||||
// Decode "base64" into "binary".
|
} else {
|
||||||
partData = Base64.decodeBase64(partData);
|
// Check Content-Transfer-Encoding.
|
||||||
} else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) {
|
byte[] partDataEncoding = part.getContentTransferEncoding();
|
||||||
// Decode "quoted-printable" into "binary".
|
if (null != partDataEncoding) {
|
||||||
partData = QuotedPrintable.decodeQuotedPrintable(partData);
|
String encoding = new String(partDataEncoding);
|
||||||
} else {
|
if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) {
|
||||||
// "binary" is the default encoding.
|
// Decode "base64" into "binary".
|
||||||
|
partData = Base64.decodeBase64(partData);
|
||||||
|
} else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) {
|
||||||
|
// Decode "quoted-printable" into "binary".
|
||||||
|
partData = QuotedPrintable.decodeQuotedPrintable(partData);
|
||||||
|
} else {
|
||||||
|
// "binary" is the default encoding.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (null == partData) {
|
||||||
|
log("Decode part data error!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
part.setData(partData);
|
||||||
}
|
}
|
||||||
if (null == partData) {
|
|
||||||
log("Decode part data error!");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
part.setData(partData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add this part to body */
|
/* add this part to body */
|
||||||
@ -905,6 +936,9 @@ public class PduParser {
|
|||||||
int temp = pduDataStream.read();
|
int temp = pduDataStream.read();
|
||||||
assert(-1 != temp);
|
assert(-1 != temp);
|
||||||
int first = temp & 0xFF;
|
int first = temp & 0xFF;
|
||||||
|
if (first == 0) {
|
||||||
|
return null; // Blank subject, bail.
|
||||||
|
}
|
||||||
|
|
||||||
pduDataStream.reset();
|
pduDataStream.reset();
|
||||||
if (first < TEXT_MIN) {
|
if (first < TEXT_MIN) {
|
||||||
@ -1529,43 +1563,61 @@ public class PduParser {
|
|||||||
* Attachment = <Octet 129>
|
* Attachment = <Octet 129>
|
||||||
* Inline = <Octet 130>
|
* Inline = <Octet 130>
|
||||||
*/
|
*/
|
||||||
int len = parseValueLength(pduDataStream);
|
|
||||||
pduDataStream.mark(1);
|
|
||||||
int thisStartPos = pduDataStream.available();
|
|
||||||
int thisEndPos = 0;
|
|
||||||
int value = pduDataStream.read();
|
|
||||||
|
|
||||||
if (value == PduPart.P_DISPOSITION_FROM_DATA ) {
|
/*
|
||||||
part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA);
|
* some carrier mmsc servers do not support content_disposition
|
||||||
} else if (value == PduPart.P_DISPOSITION_ATTACHMENT) {
|
* field correctly
|
||||||
part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT);
|
*/
|
||||||
} else if (value == PduPart.P_DISPOSITION_INLINE) {
|
Resources resources = Resources.getSystem();
|
||||||
part.setContentDisposition(PduPart.DISPOSITION_INLINE);
|
int id = resources.getIdentifier("config_mms_content_disposition_support",
|
||||||
} else {
|
"boolean", "android");
|
||||||
pduDataStream.reset();
|
|
||||||
/* Token-text */
|
|
||||||
part.setContentDisposition(parseWapString(pduDataStream, TYPE_TEXT_STRING));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get filename parameter and skip other parameters */
|
Log.w("PduParser", "config_mms_content_disposition_support ID: " + id);
|
||||||
thisEndPos = pduDataStream.available();
|
boolean contentDisposition = (id != 0) && (resources.getBoolean(id));
|
||||||
if (thisStartPos - thisEndPos < len) {
|
|
||||||
value = pduDataStream.read();
|
Log.w("PduParser", "Content Disposition supported: " + contentDisposition);
|
||||||
if (value == PduPart.P_FILENAME) { //filename is text-string
|
|
||||||
part.setFilename(parseWapString(pduDataStream, TYPE_TEXT_STRING));
|
if (contentDisposition) {
|
||||||
|
int len = parseValueLength(pduDataStream);
|
||||||
|
pduDataStream.mark(1);
|
||||||
|
int thisStartPos = pduDataStream.available();
|
||||||
|
int thisEndPos = 0;
|
||||||
|
int value = pduDataStream.read();
|
||||||
|
|
||||||
|
if (value == PduPart.P_DISPOSITION_FROM_DATA ) {
|
||||||
|
part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA);
|
||||||
|
} else if (value == PduPart.P_DISPOSITION_ATTACHMENT) {
|
||||||
|
part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT);
|
||||||
|
} else if (value == PduPart.P_DISPOSITION_INLINE) {
|
||||||
|
part.setContentDisposition(PduPart.DISPOSITION_INLINE);
|
||||||
|
} else {
|
||||||
|
pduDataStream.reset();
|
||||||
|
/* Token-text */
|
||||||
|
part.setContentDisposition(parseWapString(pduDataStream
|
||||||
|
, TYPE_TEXT_STRING));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* skip other parameters */
|
/* get filename parameter and skip other parameters */
|
||||||
thisEndPos = pduDataStream.available();
|
thisEndPos = pduDataStream.available();
|
||||||
if (thisStartPos - thisEndPos < len) {
|
if (thisStartPos - thisEndPos < len) {
|
||||||
int last = len - (thisStartPos - thisEndPos);
|
value = pduDataStream.read();
|
||||||
byte[] temp = new byte[last];
|
if (value == PduPart.P_FILENAME) { //filename is text-string
|
||||||
pduDataStream.read(temp, 0, last);
|
part.setFilename(parseWapString(pduDataStream
|
||||||
}
|
, TYPE_TEXT_STRING));
|
||||||
}
|
}
|
||||||
|
|
||||||
tempPos = pduDataStream.available();
|
/* skip other parameters */
|
||||||
lastLen = length - (startPos - tempPos);
|
thisEndPos = pduDataStream.available();
|
||||||
|
if (thisStartPos - thisEndPos < len) {
|
||||||
|
int last = len - (thisStartPos - thisEndPos);
|
||||||
|
byte[] temp = new byte[last];
|
||||||
|
pduDataStream.read(temp, 0, last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tempPos = pduDataStream.available();
|
||||||
|
lastLen = length - (startPos - tempPos);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (LOCAL_LOGV) {
|
if (LOCAL_LOGV) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user