MMS and Group Messaging Improvements

1) Display the individual sender name in a group conversation.

2) Add an "address" column to MmsDatabase and keep FROM there.

3) Remove all blocking operations from MmsDatabase.Reader path.

4) Strip SMIL and other undisplayable parts from part count.

5) Fix places where messages weren't being correctly decrypted.
pull/1/head
Moxie Marlinspike 11 years ago
parent 2305a648fb
commit 723fb4ffdd

@ -51,15 +51,17 @@ public class ConversationAdapter extends CursorAdapter implements AbsListView.Re
private final Handler failedIconClickHandler; private final Handler failedIconClickHandler;
private final Context context; private final Context context;
private final MasterSecret masterSecret; private final MasterSecret masterSecret;
private final boolean groupThread;
private final LayoutInflater inflater; private final LayoutInflater inflater;
public ConversationAdapter(Recipients recipients, long threadId, Context context, public ConversationAdapter(Context context, MasterSecret masterSecret,
MasterSecret masterSecret, Handler failedIconClickHandler) Handler failedIconClickHandler, boolean groupThread)
{ {
super(context, null); super(context, null);
this.context = context; this.context = context;
this.masterSecret = masterSecret; this.masterSecret = masterSecret;
this.failedIconClickHandler = failedIconClickHandler; this.failedIconClickHandler = failedIconClickHandler;
this.groupThread = groupThread;
this.messageRecordCache = initializeCache(); this.messageRecordCache = initializeCache();
this.inflater = (LayoutInflater)context this.inflater = (LayoutInflater)context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE); .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@ -72,7 +74,7 @@ public class ConversationAdapter extends CursorAdapter implements AbsListView.Re
String type = cursor.getString(cursor.getColumnIndexOrThrow(MmsSmsDatabase.TRANSPORT)); String type = cursor.getString(cursor.getColumnIndexOrThrow(MmsSmsDatabase.TRANSPORT));
MessageRecord messageRecord = getMessageRecord(id, cursor, type); MessageRecord messageRecord = getMessageRecord(id, cursor, type);
item.set(masterSecret, messageRecord, failedIconClickHandler); item.set(masterSecret, messageRecord, failedIconClickHandler, groupThread);
} }
@Override @Override

@ -167,8 +167,9 @@ public class ConversationFragment extends SherlockListFragment
private void initializeListAdapter() { private void initializeListAdapter() {
if (this.recipients != null && this.threadId != -1) { if (this.recipients != null && this.threadId != -1) {
this.setListAdapter(new ConversationAdapter(recipients, threadId, getActivity(), this.setListAdapter(new ConversationAdapter(getActivity(), masterSecret,
masterSecret, new FailedIconClickHandler())); new FailedIconClickHandler(),
!this.recipients.isSingleRecipient()));
getListView().setRecyclerListener((ConversationAdapter)getListAdapter()); getListView().setRecyclerListener((ConversationAdapter)getListAdapter());
getLoaderManager().initLoader(0, null, this); getLoaderManager().initLoader(0, null, this);
} }

@ -73,6 +73,7 @@ public class ConversationItem extends LinearLayout {
private Handler failedIconHandler; private Handler failedIconHandler;
private MessageRecord messageRecord; private MessageRecord messageRecord;
private MasterSecret masterSecret; private MasterSecret masterSecret;
private boolean groupThread;
private TextView bodyText; private TextView bodyText;
private TextView dateText; private TextView dateText;
@ -125,11 +126,13 @@ public class ConversationItem extends LinearLayout {
this.mmsDownloadButton.setOnClickListener(mmsDownloadClickListener); this.mmsDownloadButton.setOnClickListener(mmsDownloadClickListener);
} }
public void set(MasterSecret masterSecret, MessageRecord messageRecord, Handler failedIconHandler) public void set(MasterSecret masterSecret, MessageRecord messageRecord,
Handler failedIconHandler, boolean groupThread)
{ {
this.messageRecord = messageRecord; this.messageRecord = messageRecord;
this.masterSecret = masterSecret; this.masterSecret = masterSecret;
this.failedIconHandler = failedIconHandler; this.failedIconHandler = failedIconHandler;
this.groupThread = groupThread;
setBodyText(messageRecord); setBodyText(messageRecord);
setStatusIcons(messageRecord); setStatusIcons(messageRecord);
@ -201,19 +204,12 @@ public class ConversationItem extends LinearLayout {
} }
private void setGroupMessageStatus(MessageRecord messageRecord) { private void setGroupMessageStatus(MessageRecord messageRecord) {
// GroupData groupData = messageRecord.getGroupData(); if (groupThread && !messageRecord.isOutgoing()) {
// this.groupStatusText.setText(messageRecord.getIndividualRecipient().toShortString());
// if (groupData != null) { this.groupStatusText.setVisibility(View.VISIBLE);
// String status = String.format("Sent (%d/%d)", groupData.groupSentCount, groupData.groupSize); } else {
//
// if (groupData.groupSendFailedCount != 0)
// status = status + String.format(", Failed (%d/%d)", groupData.groupSendFailedCount, groupData.groupSize);
//
// this.groupStatusText.setText(status);
// this.groupStatusText.setVisibility(View.VISIBLE);
// } else {
this.groupStatusText.setVisibility(View.GONE); this.groupStatusText.setVisibility(View.GONE);
// } }
} }
private void setNotificationMmsAttributes(NotificationMmsMessageRecord messageRecord) { private void setNotificationMmsAttributes(NotificationMmsMessageRecord messageRecord) {
@ -242,6 +238,8 @@ public class ConversationItem extends LinearLayout {
if (messageRecord.getPartCount() > 0) { if (messageRecord.getPartCount() > 0) {
mmsThumbnail.setVisibility(View.VISIBLE); mmsThumbnail.setVisibility(View.VISIBLE);
mmsThumbnail.setImageDrawable(new ColorDrawable(Color.TRANSPARENT)); mmsThumbnail.setImageDrawable(new ColorDrawable(Color.TRANSPARENT));
} else {
mmsThumbnail.setVisibility(View.GONE);
} }
slideDeck = messageRecord.getSlideDeck(); slideDeck = messageRecord.getSlideDeck();

@ -19,6 +19,8 @@ package org.thoughtcrime.securesms.database;
import android.content.ContentValues; import android.content.ContentValues;
import android.util.Log; import android.util.Log;
import org.thoughtcrime.securesms.util.Util;
import ws.com.google.android.mms.pdu.CharacterSets; import ws.com.google.android.mms.pdu.CharacterSets;
import ws.com.google.android.mms.pdu.EncodedStringValue; import ws.com.google.android.mms.pdu.EncodedStringValue;
@ -34,14 +36,14 @@ public class ContentValuesBuilder {
public void add(String key, String charsetKey, EncodedStringValue value) { public void add(String key, String charsetKey, EncodedStringValue value) {
if (value != null) { if (value != null) {
contentValues.put(key, toIsoString(value.getTextString())); contentValues.put(key, Util.toIsoString(value.getTextString()));
contentValues.put(charsetKey, value.getCharacterSet()); contentValues.put(charsetKey, value.getCharacterSet());
} }
} }
public void add(String contentKey, byte[] value) { public void add(String contentKey, byte[] value) {
if (value != null) { if (value != null) {
contentValues.put(contentKey, toIsoString(value)); contentValues.put(contentKey, Util.toIsoString(value));
} }
} }
@ -58,14 +60,4 @@ public class ContentValuesBuilder {
public ContentValues getContentValues() { public ContentValues getContentValues() {
return contentValues; return contentValues;
} }
private String toIsoString(byte[] bytes) {
try {
return new String(bytes, CharacterSets.MIMENAME_ISO_8859_1);
} catch (UnsupportedEncodingException e) {
Log.e("MmsDatabase", "ISO_8859_1 must be supported!", e);
return "";
}
}
} }

@ -44,7 +44,8 @@ public class DatabaseFactory {
private static final int INTRODUCED_DRAFTS_VERSION = 5; private static final int INTRODUCED_DRAFTS_VERSION = 5;
private static final int INTRODUCED_NEW_TYPES_VERSION = 6; private static final int INTRODUCED_NEW_TYPES_VERSION = 6;
private static final int INTRODUCED_MMS_BODY_VERSION = 7; private static final int INTRODUCED_MMS_BODY_VERSION = 7;
private static final int DATABASE_VERSION = 7; private static final int INTRODUCED_MMS_FROM_VERSION = 8;
private static final int DATABASE_VERSION = 8;
private static final String DATABASE_NAME = "messages.db"; private static final String DATABASE_NAME = "messages.db";
private static final Object lock = new Object(); private static final Object lock = new Object();
@ -213,10 +214,14 @@ public class DatabaseFactory {
listener.setProgress(smsCursor.getCount() + threadCursor.getPosition(), count); listener.setProgress(smsCursor.getCount() + threadCursor.getPosition(), count);
try { try {
String snippet = masterCipher.decryptBody(threadCursor.getString(threadCursor.getColumnIndexOrThrow("snippet"))); String snippet = threadCursor.getString(threadCursor.getColumnIndexOrThrow("snippet"));
long snippetType = threadCursor.getLong(threadCursor.getColumnIndexOrThrow("snippet_type")); long snippetType = threadCursor.getLong(threadCursor.getColumnIndexOrThrow("snippet_type"));
long id = threadCursor.getLong(threadCursor.getColumnIndexOrThrow("_id")); long id = threadCursor.getLong(threadCursor.getColumnIndexOrThrow("_id"));
if (!Util.isEmpty(snippet)) {
snippet = masterCipher.decryptBody(snippet);
}
if (snippet.startsWith(KEY_EXCHANGE)) { if (snippet.startsWith(KEY_EXCHANGE)) {
snippet = snippet.substring(KEY_EXCHANGE.length()); snippet = snippet.substring(KEY_EXCHANGE.length());
snippet = masterCipher.encryptBody(snippet); snippet = masterCipher.encryptBody(snippet);
@ -348,6 +353,8 @@ public class DatabaseFactory {
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.beginTransaction();
if (oldVersion < INTRODUCED_IDENTITIES_VERSION) { if (oldVersion < INTRODUCED_IDENTITIES_VERSION) {
db.execSQL("CREATE TABLE identities (_id INTEGER PRIMARY KEY, key TEXT UNIQUE, name TEXT UNIQUE, mac TEXT);"); db.execSQL("CREATE TABLE identities (_id INTEGER PRIMARY KEY, key TEXT UNIQUE, name TEXT UNIQUE, mac TEXT);");
} }
@ -377,24 +384,18 @@ public class DatabaseFactory {
} }
if (oldVersion < INTRODUCED_DATE_SENT_VERSION) { if (oldVersion < INTRODUCED_DATE_SENT_VERSION) {
db.beginTransaction();
db.execSQL("ALTER TABLE sms ADD COLUMN date_sent INTEGER;"); db.execSQL("ALTER TABLE sms ADD COLUMN date_sent INTEGER;");
db.execSQL("UPDATE sms SET date_sent = date;"); db.execSQL("UPDATE sms SET date_sent = date;");
db.execSQL("ALTER TABLE mms ADD COLUMN date_received INTEGER;"); db.execSQL("ALTER TABLE mms ADD COLUMN date_received INTEGER;");
db.execSQL("UPDATE mms SET date_received = date;"); db.execSQL("UPDATE mms SET date_received = date;");
db.setTransactionSuccessful();
db.endTransaction();
} }
if (oldVersion < INTRODUCED_DRAFTS_VERSION) { if (oldVersion < INTRODUCED_DRAFTS_VERSION) {
db.beginTransaction();
db.execSQL("CREATE TABLE drafts (_id INTEGER PRIMARY KEY, thread_id INTEGER, type TEXT, value TEXT);"); db.execSQL("CREATE TABLE drafts (_id INTEGER PRIMARY KEY, thread_id INTEGER, type TEXT, value TEXT);");
executeStatements(db, new String[] { executeStatements(db, new String[] {
"CREATE INDEX IF NOT EXISTS draft_thread_index ON drafts (thread_id);", "CREATE INDEX IF NOT EXISTS draft_thread_index ON drafts (thread_id);",
}); });
db.setTransactionSuccessful();
db.endTransaction();
} }
if (oldVersion < INTRODUCED_NEW_TYPES_VERSION) { if (oldVersion < INTRODUCED_NEW_TYPES_VERSION) {
@ -405,7 +406,6 @@ public class DatabaseFactory {
String PROCESSED_KEY_EXCHANGE = "?TextSecureKeyExchangd"; String PROCESSED_KEY_EXCHANGE = "?TextSecureKeyExchangd";
String STALE_KEY_EXCHANGE = "?TextSecureKeyExchangs"; String STALE_KEY_EXCHANGE = "?TextSecureKeyExchangs";
db.beginTransaction();
// SMS Updates // SMS Updates
db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] {20L+"", 1L+""}); db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] {20L+"", 1L+""});
db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] {21L+"", 43L+""}); db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] {21L+"", 43L+""});
@ -425,26 +425,41 @@ public class DatabaseFactory {
updateSmsBodyAndType(db, cursor, SYMMETRIC_ENCRYPT, 0x80000000L); updateSmsBodyAndType(db, cursor, SYMMETRIC_ENCRYPT, 0x80000000L);
if (cursor != null)
cursor.close();
cursor = db.query("sms", null,"body LIKE ?", new String[] {ASYMMETRIC_LOCAL_ENCRYPT + "%"}, cursor = db.query("sms", null,"body LIKE ?", new String[] {ASYMMETRIC_LOCAL_ENCRYPT + "%"},
null, null, null); null, null, null);
updateSmsBodyAndType(db, cursor, ASYMMETRIC_LOCAL_ENCRYPT, 0x40000000L); updateSmsBodyAndType(db, cursor, ASYMMETRIC_LOCAL_ENCRYPT, 0x40000000L);
if (cursor != null)
cursor.close();
cursor = db.query("sms", null,"body LIKE ?", new String[] {ASYMMETRIC_ENCRYPT + "%"}, cursor = db.query("sms", null,"body LIKE ?", new String[] {ASYMMETRIC_ENCRYPT + "%"},
null, null, null); null, null, null);
updateSmsBodyAndType(db, cursor, ASYMMETRIC_ENCRYPT, 0L); updateSmsBodyAndType(db, cursor, ASYMMETRIC_ENCRYPT, 0L);
if (cursor != null)
cursor.close();
cursor = db.query("sms", null,"body LIKE ?", new String[] {KEY_EXCHANGE + "%"}, cursor = db.query("sms", null,"body LIKE ?", new String[] {KEY_EXCHANGE + "%"},
null, null, null); null, null, null);
updateSmsBodyAndType(db, cursor, KEY_EXCHANGE, 0x8000L); updateSmsBodyAndType(db, cursor, KEY_EXCHANGE, 0x8000L);
if (cursor != null)
cursor.close();
cursor = db.query("sms", null,"body LIKE ?", new String[] {PROCESSED_KEY_EXCHANGE + "%"}, cursor = db.query("sms", null,"body LIKE ?", new String[] {PROCESSED_KEY_EXCHANGE + "%"},
null, null, null); null, null, null);
updateSmsBodyAndType(db, cursor, PROCESSED_KEY_EXCHANGE, 0x8000L | 0x2000L); updateSmsBodyAndType(db, cursor, PROCESSED_KEY_EXCHANGE, 0x8000L | 0x2000L);
if (cursor != null)
cursor.close();
cursor = db.query("sms", null,"body LIKE ?", new String[] {STALE_KEY_EXCHANGE + "%"}, cursor = db.query("sms", null,"body LIKE ?", new String[] {STALE_KEY_EXCHANGE + "%"},
null, null, null); null, null, null);
@ -468,34 +483,68 @@ public class DatabaseFactory {
db.execSQL("ALTER TABLE thread ADD COLUMN snippet_type INTEGER;"); db.execSQL("ALTER TABLE thread ADD COLUMN snippet_type INTEGER;");
if (cursor != null)
cursor.close();
cursor = db.query("thread", null,"snippet LIKE ?", cursor = db.query("thread", null,"snippet LIKE ?",
new String[] {SYMMETRIC_ENCRYPT + "%"}, null, null, null); new String[] {SYMMETRIC_ENCRYPT + "%"}, null, null, null);
updateThreadSnippetAndType(db, cursor, SYMMETRIC_ENCRYPT, 0x80000000L); updateThreadSnippetAndType(db, cursor, SYMMETRIC_ENCRYPT, 0x80000000L);
if (cursor != null)
cursor.close();
cursor = db.query("thread", null,"snippet LIKE ?", cursor = db.query("thread", null,"snippet LIKE ?",
new String[] {KEY_EXCHANGE + "%"}, null, null, null); new String[] {KEY_EXCHANGE + "%"}, null, null, null);
updateThreadSnippetAndType(db, cursor, KEY_EXCHANGE, 0x8000L); updateThreadSnippetAndType(db, cursor, KEY_EXCHANGE, 0x8000L);
if (cursor != null)
cursor.close();
cursor = db.query("thread", null,"snippet LIKE ?", cursor = db.query("thread", null,"snippet LIKE ?",
new String[] {STALE_KEY_EXCHANGE + "%"}, null, null, null); new String[] {STALE_KEY_EXCHANGE + "%"}, null, null, null);
updateThreadSnippetAndType(db, cursor, STALE_KEY_EXCHANGE, 0x8000L | 0x4000L); updateThreadSnippetAndType(db, cursor, STALE_KEY_EXCHANGE, 0x8000L | 0x4000L);
if (cursor != null)
cursor.close();
cursor = db.query("thread", null,"snippet LIKE ?", cursor = db.query("thread", null,"snippet LIKE ?",
new String[] {PROCESSED_KEY_EXCHANGE + "%"}, null, null, null); new String[] {PROCESSED_KEY_EXCHANGE + "%"}, null, null, null);
updateThreadSnippetAndType(db, cursor, KEY_EXCHANGE, 0x8000L | 0x2000L); updateThreadSnippetAndType(db, cursor, KEY_EXCHANGE, 0x8000L | 0x2000L);
db.setTransactionSuccessful(); if (cursor != null)
db.endTransaction(); cursor.close();
} }
if (oldVersion < INTRODUCED_MMS_BODY_VERSION) { if (oldVersion < INTRODUCED_MMS_BODY_VERSION) {
db.execSQL("ALTER TABLE mms ADD COLUMN body TEXT"); db.execSQL("ALTER TABLE mms ADD COLUMN body TEXT");
db.execSQL("ALTER TABLE mms ADD COLUMN part_count INTEGER"); db.execSQL("ALTER TABLE mms ADD COLUMN part_count INTEGER");
} }
if (oldVersion < INTRODUCED_MMS_FROM_VERSION) {
db.execSQL("ALTER TABLE mms ADD COLUMN address TEXT");
Cursor cursor = db.query("mms_addresses", null, "type = ?", new String[] {0x89+""},
null, null, null);
while (cursor != null && cursor.moveToNext()) {
long mmsId = cursor.getLong(cursor.getColumnIndexOrThrow("mms_id"));
String address = cursor.getString(cursor.getColumnIndexOrThrow("address"));
if (!Util.isEmpty(address)) {
db.execSQL("UPDATE mms SET address = ? WHERE _id = ?", new String[]{address, mmsId+""});
}
}
if (cursor != null)
cursor.close();
}
db.setTransactionSuccessful();
db.endTransaction();
} }
private void updateSmsBodyAndType(SQLiteDatabase db, Cursor cursor, String prefix, long typeMask) private void updateSmsBodyAndType(SQLiteDatabase db, Cursor cursor, String prefix, long typeMask)

@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord; import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord;
import org.thoughtcrime.securesms.mms.PartParser; import org.thoughtcrime.securesms.mms.PartParser;
import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.mms.TextSlide;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.RecipientFormattingException; import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
@ -75,19 +76,19 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
private static final String MESSAGE_ID = "m_id"; private static final String MESSAGE_ID = "m_id";
private static final String SUBJECT = "sub"; private static final String SUBJECT = "sub";
private static final String SUBJECT_CHARSET = "sub_cs"; private static final String SUBJECT_CHARSET = "sub_cs";
private static final String CONTENT_TYPE = "ct_t"; static final String CONTENT_TYPE = "ct_t";
private static final String CONTENT_LOCATION = "ct_l"; static final String CONTENT_LOCATION = "ct_l";
private static final String EXPIRY = "exp"; static final String EXPIRY = "exp";
private static final String MESSAGE_CLASS = "m_cls"; private static final String MESSAGE_CLASS = "m_cls";
public static final String MESSAGE_TYPE = "m_type"; public static final String MESSAGE_TYPE = "m_type";
private static final String MMS_VERSION = "v"; private static final String MMS_VERSION = "v";
private static final String MESSAGE_SIZE = "m_size"; static final String MESSAGE_SIZE = "m_size";
private static final String PRIORITY = "pri"; private static final String PRIORITY = "pri";
private static final String READ_REPORT = "rr"; private static final String READ_REPORT = "rr";
private static final String REPORT_ALLOWED = "rpt_a"; private static final String REPORT_ALLOWED = "rpt_a";
private static final String RESPONSE_STATUS = "resp_st"; private static final String RESPONSE_STATUS = "resp_st";
private static final String STATUS = "st"; static final String STATUS = "st";
private static final String TRANSACTION_ID = "tr_id"; static final String TRANSACTION_ID = "tr_id";
private static final String RETRIEVE_STATUS = "retr_st"; private static final String RETRIEVE_STATUS = "retr_st";
private static final String RETRIEVE_TEXT = "retr_txt"; private static final String RETRIEVE_TEXT = "retr_txt";
private static final String RETRIEVE_TEXT_CS = "retr_txt_cs"; private static final String RETRIEVE_TEXT_CS = "retr_txt_cs";
@ -102,7 +103,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
THREAD_ID + " INTEGER, " + DATE_SENT + " INTEGER, " + DATE_RECEIVED + " INTEGER, " + MESSAGE_BOX + " INTEGER, " + THREAD_ID + " INTEGER, " + DATE_SENT + " INTEGER, " + DATE_RECEIVED + " INTEGER, " + MESSAGE_BOX + " INTEGER, " +
READ + " INTEGER DEFAULT 0, " + MESSAGE_ID + " TEXT, " + SUBJECT + " TEXT, " + READ + " INTEGER DEFAULT 0, " + MESSAGE_ID + " TEXT, " + SUBJECT + " TEXT, " +
SUBJECT_CHARSET + " INTEGER, " + BODY + " TEXT, " + PART_COUNT + " INTEGER, " + SUBJECT_CHARSET + " INTEGER, " + BODY + " TEXT, " + PART_COUNT + " INTEGER, " +
CONTENT_TYPE + " TEXT, " + CONTENT_LOCATION + " TEXT, " + CONTENT_TYPE + " TEXT, " + CONTENT_LOCATION + " TEXT, " + ADDRESS + " TEXT, " +
EXPIRY + " INTEGER, " + MESSAGE_CLASS + " TEXT, " + MESSAGE_TYPE + " INTEGER, " + EXPIRY + " INTEGER, " + MESSAGE_CLASS + " TEXT, " + MESSAGE_TYPE + " INTEGER, " +
MMS_VERSION + " INTEGER, " + MESSAGE_SIZE + " INTEGER, " + PRIORITY + " INTEGER, " + MMS_VERSION + " INTEGER, " + MESSAGE_SIZE + " INTEGER, " + PRIORITY + " INTEGER, " +
READ_REPORT + " INTEGER, " + REPORT_ALLOWED + " INTEGER, " + RESPONSE_STATUS + " INTEGER, " + READ_REPORT + " INTEGER, " + REPORT_ALLOWED + " INTEGER, " + RESPONSE_STATUS + " INTEGER, " +
@ -125,7 +126,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
CONTENT_LOCATION, EXPIRY, MESSAGE_CLASS, MESSAGE_TYPE, MMS_VERSION, CONTENT_LOCATION, EXPIRY, MESSAGE_CLASS, MESSAGE_TYPE, MMS_VERSION,
MESSAGE_SIZE, PRIORITY, REPORT_ALLOWED, STATUS, TRANSACTION_ID, RETRIEVE_STATUS, MESSAGE_SIZE, PRIORITY, REPORT_ALLOWED, STATUS, TRANSACTION_ID, RETRIEVE_STATUS,
RETRIEVE_TEXT, RETRIEVE_TEXT_CS, READ_STATUS, CONTENT_CLASS, RESPONSE_TEXT, RETRIEVE_TEXT, RETRIEVE_TEXT_CS, READ_STATUS, CONTENT_CLASS, RESPONSE_TEXT,
DELIVERY_TIME, DELIVERY_REPORT, BODY, PART_COUNT DELIVERY_TIME, DELIVERY_REPORT, BODY, PART_COUNT, ADDRESS
}; };
public static final ExecutorService slideResolver = Util.newSingleThreadedLifoExecutor(); public static final ExecutorService slideResolver = Util.newSingleThreadedLifoExecutor();
@ -208,35 +209,6 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
} }
} }
public Recipient getMessageRecipient(long messageId) {
try {
PduHeaders headers = new PduHeaders();
MmsAddressDatabase database = DatabaseFactory.getMmsAddressDatabase(context);
database.getAddressesForId(messageId, headers);
EncodedStringValue encodedFrom = headers.getEncodedStringValue(PduHeaders.FROM);
if (encodedFrom != null) {
String address = new String(encodedFrom.getTextString(), CharacterSets.MIMENAME_ISO_8859_1);
Recipients recipients = RecipientFactory.getRecipientsFromString(context, address, false);
if (recipients == null || recipients.isEmpty()) {
return new Recipient("Unknown", "Unknown", null,
ContactPhotoFactory.getDefaultContactPhoto(context));
}
return recipients.getPrimaryRecipient();
} else {
return new Recipient("Unknown", "Unknown", null,
ContactPhotoFactory.getDefaultContactPhoto(context));
}
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
} catch (RecipientFormattingException e) {
return new Recipient("Unknown", "Unknown", null,
ContactPhotoFactory.getDefaultContactPhoto(context));
}
}
public void updateResponseStatus(long messageId, int status) { public void updateResponseStatus(long messageId, int status) {
SQLiteDatabase database = databaseHelper.getWritableDatabase(); SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues(); ContentValues contentValues = new ContentValues();
@ -295,40 +267,29 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
database.update(TABLE_NAME, contentValues, THREAD_ID + " = ?", new String[] {threadId+""}); database.update(TABLE_NAME, contentValues, THREAD_ID + " = ?", new String[] {threadId+""});
} }
public NotificationInd getNotificationMessage(long messageId) throws MmsException { public SendReq[] getOutgoingMessages(MasterSecret masterSecret, long messageId)
PduHeaders headers = getHeadersForId(messageId);
return new NotificationInd(headers);
}
private MultimediaMessagePdu getMediaMessage(long messageId)
throws MmsException throws MmsException
{ {
PduHeaders headers = getHeadersForId(messageId); MmsAddressDatabase addr = DatabaseFactory.getMmsAddressDatabase(context);
PartDatabase partDatabase = getPartDatabase(null); PartDatabase parts = getPartDatabase(masterSecret);
PduBody body = partDatabase.getParts(messageId, false); SQLiteDatabase database = databaseHelper.getReadableDatabase();
MasterCipher masterCipher = masterSecret == null ? null : new MasterCipher(masterSecret);
return new MultimediaMessagePdu(headers, body); Cursor cursor = null;
}
public SendReq getSendRequest(MasterSecret masterSecret, long messageId) throws MmsException { String selection;
PduHeaders headers = getHeadersForId(messageId); String[] selectionArgs;
PartDatabase partDatabase = getPartDatabase(masterSecret);
PduBody body = partDatabase.getParts(messageId, true); if (messageId > 0) {
selection = ID_WHERE;
return new SendReq(headers, body, messageId, headers.getMessageBox()); selectionArgs = new String[]{messageId + ""};
} } else {
selection = MESSAGE_BOX + " & " + Types.BASE_TYPE_MASK + " = ?";
public SendReq[] getOutgoingMessages(MasterSecret masterSecret) throws MmsException { selectionArgs = new String[]{Types.BASE_OUTBOX_TYPE + ""};
MmsAddressDatabase addr = DatabaseFactory.getMmsAddressDatabase(context); }
PartDatabase parts = getPartDatabase(masterSecret);
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = null;
try { try {
cursor = database.query(TABLE_NAME, MMS_PROJECTION, cursor = database.query(TABLE_NAME, MMS_PROJECTION, selection, selectionArgs, null, null, null);
MESSAGE_BOX + " & " + Types.BASE_TYPE_MASK + " = ?",
new String[] {Types.BASE_OUTBOX_TYPE+""},
null, null, null);
if (cursor == null || cursor.getCount() == 0) if (cursor == null || cursor.getCount() == 0)
return new SendReq[0]; return new SendReq[0];
@ -337,12 +298,25 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
int i = 0; int i = 0;
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
long messageId = cursor.getLong(cursor.getColumnIndexOrThrow(ID)); messageId = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX)); long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
PduHeaders headers = getHeadersFromCursor(cursor); String messageText = cursor.getString(cursor.getColumnIndexOrThrow(BODY));
PduHeaders headers = getHeadersFromCursor(cursor);
addr.getAddressesForId(messageId, headers); addr.getAddressesForId(messageId, headers);
PduBody body = parts.getParts(messageId, true); PduBody body = parts.getParts(messageId, true);
requests[i++] = new SendReq(headers, body, messageId, outboxType);
try {
if (!Util.isEmpty(messageText) && Types.isSymmetricEncryption(outboxType)) {
body.addPart(new TextSlide(context, masterCipher.decryptBody(messageText)).getPart());
} else if (!Util.isEmpty(messageText)) {
body.addPart(new TextSlide(context, messageText).getPart());
}
} catch (InvalidMessageException e) {
Log.w("MmsDatabase", e);
}
requests[i++] = new SendReq(headers, body, messageId, outboxType);
} }
return requests; return requests;
@ -467,6 +441,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
contentValues.put(THREAD_ID, threadId); contentValues.put(THREAD_ID, threadId);
contentValues.put(READ, 1); contentValues.put(READ, 1);
contentValues.put(DATE_RECEIVED, contentValues.getAsLong(DATE_SENT)); contentValues.put(DATE_RECEIVED, contentValues.getAsLong(DATE_SENT));
contentValues.remove(ADDRESS);
long messageId = insertMediaMessage(masterSecret, sendRequest, contentValues); long messageId = insertMediaMessage(masterSecret, sendRequest, contentValues);
Trimmer.trimThread(context, threadId); Trimmer.trimThread(context, threadId);
@ -493,7 +468,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
} }
} }
contentValues.put(PART_COUNT, body.getPartsNum()); contentValues.put(PART_COUNT, PartParser.getDisplayablePartCount(body));
long messageId = db.insert(TABLE_NAME, null, contentValues); long messageId = db.insert(TABLE_NAME, null, contentValues);
@ -601,31 +576,6 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
} }
} }
private PduHeaders getHeadersForId(long messageId) throws MmsException {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = null;
try {
cursor = database.query(TABLE_NAME, MMS_PROJECTION, ID_WHERE, new String[] {messageId+""},
null, null, null);
if (cursor == null || !cursor.moveToFirst())
throw new MmsException("No headers available at ID: " + messageId);
PduHeaders headers = getHeadersFromCursor(cursor);
long messageBox = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
MmsAddressDatabase addr = DatabaseFactory.getMmsAddressDatabase(context);
addr.getAddressesForId(messageId, headers);
headers.setMessageBox(messageBox);
return headers;
} finally {
if (cursor != null)
cursor.close();
}
}
private PduHeaders getHeadersFromCursor(Cursor cursor) throws InvalidHeaderValueException { private PduHeaders getHeadersFromCursor(Cursor cursor) throws InvalidHeaderValueException {
PduHeaders headers = new PduHeaders(); PduHeaders headers = new PduHeaders();
PduHeadersBuilder phb = new PduHeadersBuilder(headers, cursor); PduHeadersBuilder phb = new PduHeadersBuilder(headers, cursor);
@ -683,6 +633,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
cvb.add(DELIVERY_TIME, headers.getLongInteger(PduHeaders.DELIVERY_TIME)); cvb.add(DELIVERY_TIME, headers.getLongInteger(PduHeaders.DELIVERY_TIME));
cvb.add(EXPIRY, headers.getLongInteger(PduHeaders.EXPIRY)); cvb.add(EXPIRY, headers.getLongInteger(PduHeaders.EXPIRY));
cvb.add(MESSAGE_SIZE, headers.getLongInteger(PduHeaders.MESSAGE_SIZE)); cvb.add(MESSAGE_SIZE, headers.getLongInteger(PduHeaders.MESSAGE_SIZE));
cvb.add(ADDRESS, headers.getEncodedStringValue(PduHeaders.FROM).getTextString());
return cvb.getContentValues(); return cvb.getContentValues();
} }
@ -759,23 +710,76 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
} }
} }
private NotificationMmsMessageRecord getNotificationMmsMessageRecord(Cursor cursor) {
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.ID));
long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_SENT));
long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_RECEIVED));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.THREAD_ID));
long mailbox = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
String address = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS));
Recipients recipients = getRecipientsFor(address);
String contentLocation = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.CONTENT_LOCATION));
String transactionId = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.TRANSACTION_ID));
long messageSize = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_SIZE));
long expiry = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRY));
int status = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.STATUS));
byte[]contentLocationBytes = null;
byte[]transactionIdBytes = null;
if (!Util.isEmpty(contentLocation))
contentLocationBytes = Util.toIsoBytes(contentLocation);
if (!Util.isEmpty(transactionId))
transactionIdBytes = Util.toIsoBytes(transactionId);
return new NotificationMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
dateSent, dateReceived, threadId, contentLocationBytes,
messageSize, expiry, status, transactionIdBytes, mailbox);
}
private MediaMmsMessageRecord getMediaMmsMessageRecord(Cursor cursor) { private MediaMmsMessageRecord getMediaMmsMessageRecord(Cursor cursor) {
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.ID)); long id = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.ID));
long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_SENT)); long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_SENT));
long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_RECEIVED)); long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_RECEIVED));
long box = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX)); long box = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.THREAD_ID)); long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.THREAD_ID));
String address = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS));
DisplayRecord.Body body = getBody(cursor); DisplayRecord.Body body = getBody(cursor);
int partCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.PART_COUNT)); int partCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.PART_COUNT));
Recipient recipient = getMessageRecipient(id); Recipients recipients = getRecipientsFor(address);
ListenableFutureTask<SlideDeck> slideDeck = getSlideDeck(masterSecret, id); ListenableFutureTask<SlideDeck> slideDeck = getSlideDeck(masterSecret, id);
return new MediaMmsMessageRecord(context, id, new Recipients(recipient), recipient, return new MediaMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
dateSent, dateReceived, threadId, body, dateSent, dateReceived, threadId, body,
slideDeck, partCount, box); slideDeck, partCount, box);
} }
private Recipients getRecipientsFor(String address) {
try {
if (Util.isEmpty(address)) {
return new Recipients(new Recipient("Unknown", "Unknown", null,
ContactPhotoFactory.getDefaultContactPhoto(context)));
}
Recipients recipients = RecipientFactory.getRecipientsFromString(context, address, false);
if (recipients == null || recipients.isEmpty()) {
return new Recipients(new Recipient("Unknown", "Unknown", null,
ContactPhotoFactory.getDefaultContactPhoto(context)));
}
return recipients;
} catch (RecipientFormattingException e) {
Log.w("MmsDatabase", e);
return new Recipients(new Recipient("Unknown", "Unknown", null,
ContactPhotoFactory.getDefaultContactPhoto(context)));
}
}
private DisplayRecord.Body getBody(Cursor cursor) { private DisplayRecord.Body getBody(Cursor cursor) {
try { try {
String body = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.BODY)); String body = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.BODY));
@ -800,17 +804,11 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
Callable<SlideDeck> task = new Callable<SlideDeck>() { Callable<SlideDeck> task = new Callable<SlideDeck>() {
@Override @Override
public SlideDeck call() throws Exception { public SlideDeck call() throws Exception {
try { if (masterSecret == null)
if (masterSecret == null)
return null;
MultimediaMessagePdu pdu = getMediaMessage(id);
return new SlideDeck(context, masterSecret, pdu.getBody());
} catch (MmsException me) {
Log.w("MmsDatabase", me);
return null; return null;
}
PduBody body = getPartDatabase(masterSecret).getParts(id, false);
return new SlideDeck(context, masterSecret, body);
} }
}; };
@ -820,34 +818,6 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
return future; return future;
} }
private NotificationMmsMessageRecord getNotificationMmsMessageRecord(Cursor cursor) {
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.ID));
long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_SENT));
long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_RECEIVED));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.THREAD_ID));
long mailbox = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
Recipient recipient = getMessageRecipient(id);
NotificationInd notification;
try {
notification = getNotificationMessage(id);
} catch (MmsException me) {
Log.w("ConversationAdapter", me);
notification = new NotificationInd(new PduHeaders());
}
return new NotificationMmsMessageRecord(context, id, new Recipients(recipient), recipient,
dateSent, dateReceived, threadId,
notification.getContentLocation(),
notification.getMessageSize(),
notification.getExpiry(),
notification.getStatus(),
notification.getTransactionId(),
mailbox);
}
public void close() { public void close() {
cursor.close(); cursor.close();
} }

@ -8,6 +8,8 @@ public interface MmsSmsColumns {
public static final String THREAD_ID = "thread_id"; public static final String THREAD_ID = "thread_id";
public static final String READ = "read"; public static final String READ = "read";
public static final String BODY = "body"; public static final String BODY = "body";
public static final String ADDRESS = "address";
public static class Types { public static class Types {
protected static final long TOTAL_MASK = 0xFFFFFFFF; protected static final long TOTAL_MASK = 0xFFFFFFFF;

@ -39,54 +39,6 @@ public class MmsSmsDatabase extends Database {
super(context, databaseHelper); super(context, databaseHelper);
} }
// public Cursor getCollatedGroupConversation(long threadId) {
// String smsCaseSecurity = "CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " " +
// "WHEN " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " THEN 1 " +
// "ELSE 0 END";
//
// String mmsCaseSecurity = "CASE " + MmsDatabase.MESSAGE_BOX + " & " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " " +
// "WHEN " + MmsDatabase.Types.SECURE_MESSAGE_BIT + " THEN 'secure' " +
// "ELSE 'insecure' END";
//
// String mmsGroupSentCount = "SUM(CASE " + MmsDatabase.MESSAGE_BOX + " & " + MmsDatabase.Types.BASE_TYPE_MASK + " " +
// "WHEN " + MmsDatabase.Types.BASE_SENT_TYPE + " THEN 1 " +
// "ELSE 0 END)";
//
//
// String smsGroupSentCount = "SUM(CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.BASE_TYPE_MASK + " " +
// "WHEN " + SmsDatabase.Types.BASE_SENT_TYPE + " THEN 1 " +
// "ELSE 0 END)";
//
// String mmsGroupSentFailedCount = "SUM(CASE " + MmsDatabase.MESSAGE_BOX + " & " + MmsDatabase.Types.BASE_TYPE_MASK + " " +
// "WHEN " + MmsDatabase.Types.BASE_SENT_FAILED_TYPE + " THEN 1 " +
// "ELSE 0 END)";
//
// String smsGroupSentFailedCount = "SUM(CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.BASE_TYPE_MASK + " " +
// "WHEN " + SmsDatabase.Types.BASE_SENT_FAILED_TYPE + " THEN 1 " +
// "ELSE 0 END)";
//
// String[] projection = {MmsSmsColumns.ID, SmsDatabase.BODY, SmsDatabase.TYPE,
// MmsSmsColumns.THREAD_ID,
// SmsDatabase.ADDRESS, SmsDatabase.SUBJECT, SmsDatabase.STATUS,
// MmsSmsColumns.NORMALIZED_DATE_SENT, MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
// MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX, TRANSPORT,
// "COUNT(" + MmsSmsColumns.ID + ") AS " + GROUP_SIZE,
// mmsGroupSentCount + " AS " + MMS_GROUP_SENT_COUNT,
// mmsGroupSentFailedCount + " AS " + MMS_GROUP_SEND_FAILED_COUNT,
// smsGroupSentCount + " AS " + SMS_GROUP_SENT_COUNT,
// smsGroupSentFailedCount + " AS " + SMS_GROUP_SEND_FAILED_COUNT,
// smsCaseSecurity + " AS sms_collate", mmsCaseSecurity + " AS mms_collate"};
//
// String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC";
// String selection = MmsSmsColumns.THREAD_ID + " = " + threadId;
// String groupBy = MmsSmsColumns.NORMALIZED_DATE_SENT + " / 1000, sms_collate, mms_collate";
//
// Cursor cursor = queryTables(projection, selection, order, groupBy, null);
// setNotifyConverationListeners(cursor, threadId);
//
// return cursor;
// }
public Cursor getConversation(long threadId) { public Cursor getConversation(long threadId) {
String[] projection = {MmsSmsColumns.ID, SmsDatabase.BODY, SmsDatabase.TYPE, String[] projection = {MmsSmsColumns.ID, SmsDatabase.BODY, SmsDatabase.TYPE,
MmsSmsColumns.THREAD_ID, MmsSmsColumns.THREAD_ID,
@ -94,7 +46,10 @@ public class MmsSmsDatabase extends Database {
MmsSmsColumns.NORMALIZED_DATE_SENT, MmsSmsColumns.NORMALIZED_DATE_SENT,
MmsSmsColumns.NORMALIZED_DATE_RECEIVED, MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX, MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX,
SmsDatabase.STATUS, MmsDatabase.PART_COUNT, TRANSPORT}; SmsDatabase.STATUS, MmsDatabase.PART_COUNT,
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY,
MmsDatabase.STATUS, TRANSPORT};
String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC"; String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC";
@ -113,7 +68,11 @@ public class MmsSmsDatabase extends Database {
MmsSmsColumns.NORMALIZED_DATE_SENT, MmsSmsColumns.NORMALIZED_DATE_SENT,
MmsSmsColumns.NORMALIZED_DATE_RECEIVED, MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX, MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX,
SmsDatabase.STATUS, MmsDatabase.PART_COUNT, TRANSPORT}; SmsDatabase.STATUS, MmsDatabase.PART_COUNT,
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY,
MmsDatabase.STATUS, TRANSPORT};
String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC"; String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC";
String selection = MmsSmsColumns.THREAD_ID + " = " + threadId; String selection = MmsSmsColumns.THREAD_ID + " = " + threadId;
@ -127,7 +86,11 @@ public class MmsSmsDatabase extends Database {
MmsSmsColumns.NORMALIZED_DATE_SENT, MmsSmsColumns.NORMALIZED_DATE_SENT,
MmsSmsColumns.NORMALIZED_DATE_RECEIVED, MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX, MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX,
MmsDatabase.PART_COUNT, TRANSPORT}; MmsDatabase.PART_COUNT,
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY,
MmsDatabase.STATUS, TRANSPORT};
String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC"; String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC";
String selection = MmsSmsColumns.READ + " = 0"; String selection = MmsSmsColumns.READ + " = 0";
@ -146,13 +109,19 @@ public class MmsSmsDatabase extends Database {
MmsDatabase.DATE_RECEIVED + " * 1000 AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED, MmsDatabase.DATE_RECEIVED + " * 1000 AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
MmsSmsColumns.ID, SmsDatabase.BODY, MmsSmsColumns.READ, MmsSmsColumns.THREAD_ID, MmsSmsColumns.ID, SmsDatabase.BODY, MmsSmsColumns.READ, MmsSmsColumns.THREAD_ID,
SmsDatabase.TYPE, SmsDatabase.ADDRESS, SmsDatabase.SUBJECT, MmsDatabase.MESSAGE_TYPE, SmsDatabase.TYPE, SmsDatabase.ADDRESS, SmsDatabase.SUBJECT, MmsDatabase.MESSAGE_TYPE,
MmsDatabase.MESSAGE_BOX, SmsDatabase.STATUS, MmsDatabase.PART_COUNT, TRANSPORT}; MmsDatabase.MESSAGE_BOX, SmsDatabase.STATUS, MmsDatabase.PART_COUNT,
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY, MmsDatabase.STATUS,
TRANSPORT};
String[] smsProjection = {SmsDatabase.DATE_SENT + " * 1 AS " + MmsSmsColumns.NORMALIZED_DATE_SENT, String[] smsProjection = {SmsDatabase.DATE_SENT + " * 1 AS " + MmsSmsColumns.NORMALIZED_DATE_SENT,
SmsDatabase.DATE_RECEIVED + " * 1 AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED, SmsDatabase.DATE_RECEIVED + " * 1 AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
MmsSmsColumns.ID, SmsDatabase.BODY, MmsSmsColumns.READ, MmsSmsColumns.THREAD_ID, MmsSmsColumns.ID, SmsDatabase.BODY, MmsSmsColumns.READ, MmsSmsColumns.THREAD_ID,
SmsDatabase.TYPE, SmsDatabase.ADDRESS, SmsDatabase.SUBJECT, MmsDatabase.MESSAGE_TYPE, SmsDatabase.TYPE, SmsDatabase.ADDRESS, SmsDatabase.SUBJECT, MmsDatabase.MESSAGE_TYPE,
MmsDatabase.MESSAGE_BOX, SmsDatabase.STATUS, MmsDatabase.PART_COUNT, TRANSPORT}; MmsDatabase.MESSAGE_BOX, SmsDatabase.STATUS, MmsDatabase.PART_COUNT,
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY, MmsDatabase.STATUS,
TRANSPORT};
SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder(); SQLiteQueryBuilder mmsQueryBuilder = new SQLiteQueryBuilder();
@ -166,25 +135,31 @@ public class MmsSmsDatabase extends Database {
Set<String> mmsColumnsPresent = new HashSet<String>(); Set<String> mmsColumnsPresent = new HashSet<String>();
mmsColumnsPresent.add(MmsSmsColumns.ID); mmsColumnsPresent.add(MmsSmsColumns.ID);
mmsColumnsPresent.add(MmsSmsColumns.READ);
mmsColumnsPresent.add(MmsSmsColumns.THREAD_ID);
mmsColumnsPresent.add(MmsSmsColumns.BODY);
mmsColumnsPresent.add(MmsSmsColumns.ADDRESS);
mmsColumnsPresent.add(MmsDatabase.MESSAGE_TYPE); mmsColumnsPresent.add(MmsDatabase.MESSAGE_TYPE);
mmsColumnsPresent.add(MmsDatabase.MESSAGE_BOX); mmsColumnsPresent.add(MmsDatabase.MESSAGE_BOX);
mmsColumnsPresent.add(MmsDatabase.DATE_SENT); mmsColumnsPresent.add(MmsDatabase.DATE_SENT);
mmsColumnsPresent.add(MmsDatabase.DATE_RECEIVED); mmsColumnsPresent.add(MmsDatabase.DATE_RECEIVED);
mmsColumnsPresent.add(MmsSmsColumns.READ);
mmsColumnsPresent.add(MmsSmsColumns.THREAD_ID);
mmsColumnsPresent.add(MmsSmsColumns.BODY);
mmsColumnsPresent.add(MmsDatabase.PART_COUNT); mmsColumnsPresent.add(MmsDatabase.PART_COUNT);
mmsColumnsPresent.add(MmsDatabase.CONTENT_LOCATION);
mmsColumnsPresent.add(MmsDatabase.TRANSACTION_ID);
mmsColumnsPresent.add(MmsDatabase.MESSAGE_SIZE);
mmsColumnsPresent.add(MmsDatabase.EXPIRY);
mmsColumnsPresent.add(MmsDatabase.STATUS);
Set<String> smsColumnsPresent = new HashSet<String>(); Set<String> smsColumnsPresent = new HashSet<String>();
smsColumnsPresent.add(MmsSmsColumns.ID); smsColumnsPresent.add(MmsSmsColumns.ID);
smsColumnsPresent.add(MmsSmsColumns.BODY); smsColumnsPresent.add(MmsSmsColumns.BODY);
smsColumnsPresent.add(MmsSmsColumns.ADDRESS);
smsColumnsPresent.add(MmsSmsColumns.READ);
smsColumnsPresent.add(MmsSmsColumns.THREAD_ID);
smsColumnsPresent.add(SmsDatabase.TYPE); smsColumnsPresent.add(SmsDatabase.TYPE);
smsColumnsPresent.add(SmsDatabase.ADDRESS);
smsColumnsPresent.add(SmsDatabase.SUBJECT); smsColumnsPresent.add(SmsDatabase.SUBJECT);
smsColumnsPresent.add(SmsDatabase.DATE_SENT); smsColumnsPresent.add(SmsDatabase.DATE_SENT);
smsColumnsPresent.add(SmsDatabase.DATE_RECEIVED); smsColumnsPresent.add(SmsDatabase.DATE_RECEIVED);
smsColumnsPresent.add(MmsSmsColumns.READ);
smsColumnsPresent.add(MmsSmsColumns.THREAD_ID);
smsColumnsPresent.add(SmsDatabase.STATUS); smsColumnsPresent.add(SmsDatabase.STATUS);
String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery(TRANSPORT, mmsProjection, mmsColumnsPresent, 2, MMS_TRANSPORT, selection, null, null, null); String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery(TRANSPORT, mmsProjection, mmsColumnsPresent, 2, MMS_TRANSPORT, selection, null, null, null);

@ -52,7 +52,6 @@ import java.util.Set;
public class SmsDatabase extends Database implements MmsSmsColumns { public class SmsDatabase extends Database implements MmsSmsColumns {
public static final String TABLE_NAME = "sms"; public static final String TABLE_NAME = "sms";
public static final String ADDRESS = "address";
public static final String PERSON = "person"; public static final String PERSON = "person";
static final String DATE_RECEIVED = "date"; static final String DATE_RECEIVED = "date";
static final String DATE_SENT = "date_sent"; static final String DATE_SENT = "date_sent";
@ -61,7 +60,6 @@ public class SmsDatabase extends Database implements MmsSmsColumns {
public static final String TYPE = "type"; public static final String TYPE = "type";
public static final String REPLY_PATH_PRESENT = "reply_path_present"; public static final String REPLY_PATH_PRESENT = "reply_path_present";
public static final String SUBJECT = "subject"; public static final String SUBJECT = "subject";
//public static final String BODY = "body";
public static final String SERVICE_CENTER = "service_center"; public static final String SERVICE_CENTER = "service_center";
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " integer PRIMARY KEY, " + public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " integer PRIMARY KEY, " +

@ -75,7 +75,7 @@ public class MediaMmsMessageRecord extends MessageRecord {
return emphasisAdded(context.getString(R.string.MmsMessageRecord_bad_encrypted_mms_message)); return emphasisAdded(context.getString(R.string.MmsMessageRecord_bad_encrypted_mms_message));
} else if (MmsDatabase.Types.isNoRemoteSessionType(type)) { } else if (MmsDatabase.Types.isNoRemoteSessionType(type)) {
return emphasisAdded(context.getString(R.string.MmsMessageRecord_mms_message_encrypted_for_non_existing_session)); return emphasisAdded(context.getString(R.string.MmsMessageRecord_mms_message_encrypted_for_non_existing_session));
} else if (getBody().isPlaintext()) { } else if (!getBody().isPlaintext()) {
return emphasisAdded(context.getString(R.string.MessageNotifier_encrypted_message)); return emphasisAdded(context.getString(R.string.MessageNotifier_encrypted_message));
} }

@ -44,4 +44,21 @@ public class PartParser {
return stripped; return stripped;
} }
public static int getDisplayablePartCount(PduBody body) {
int partCount = 0;
for (int i=0;i<body.getPartsNum();i++) {
String contentType = Util.toIsoString(body.getPart(i).getContentType());
if (ContentType.isImageType(contentType) ||
ContentType.isAudioType(contentType) ||
ContentType.isVideoType(contentType))
{
partCount++;
}
}
return partCount;
}
} }

@ -165,16 +165,7 @@ public class MmsSender extends MmscProcessor {
throws MmsException throws MmsException
{ {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context); MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
List<SendReq> sendRequests; return Arrays.asList(database.getOutgoingMessages(masterSecret, messageId));
if (messageId == -1) {
sendRequests = Arrays.asList(database.getOutgoingMessages(masterSecret));
} else {
sendRequests = new ArrayList<SendReq>(1);
sendRequests.add(database.getSendRequest(masterSecret, messageId));
}
return sendRequests;
} }
protected void handleConnectivityChange() { protected void handleConnectivityChange() {

Loading…
Cancel
Save