diff --git a/src/org/thoughtcrime/securesms/ConversationAdapter.java b/src/org/thoughtcrime/securesms/ConversationAdapter.java index 551ceac304..eb49dd8f47 100644 --- a/src/org/thoughtcrime/securesms/ConversationAdapter.java +++ b/src/org/thoughtcrime/securesms/ConversationAdapter.java @@ -51,15 +51,17 @@ public class ConversationAdapter extends CursorAdapter implements AbsListView.Re private final Handler failedIconClickHandler; private final Context context; private final MasterSecret masterSecret; + private final boolean groupThread; private final LayoutInflater inflater; - public ConversationAdapter(Recipients recipients, long threadId, Context context, - MasterSecret masterSecret, Handler failedIconClickHandler) + public ConversationAdapter(Context context, MasterSecret masterSecret, + Handler failedIconClickHandler, boolean groupThread) { super(context, null); this.context = context; this.masterSecret = masterSecret; this.failedIconClickHandler = failedIconClickHandler; + this.groupThread = groupThread; this.messageRecordCache = initializeCache(); this.inflater = (LayoutInflater)context .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)); MessageRecord messageRecord = getMessageRecord(id, cursor, type); - item.set(masterSecret, messageRecord, failedIconClickHandler); + item.set(masterSecret, messageRecord, failedIconClickHandler, groupThread); } @Override diff --git a/src/org/thoughtcrime/securesms/ConversationFragment.java b/src/org/thoughtcrime/securesms/ConversationFragment.java index e458df0e9d..b6ae5f368a 100644 --- a/src/org/thoughtcrime/securesms/ConversationFragment.java +++ b/src/org/thoughtcrime/securesms/ConversationFragment.java @@ -167,8 +167,9 @@ public class ConversationFragment extends SherlockListFragment private void initializeListAdapter() { if (this.recipients != null && this.threadId != -1) { - this.setListAdapter(new ConversationAdapter(recipients, threadId, getActivity(), - masterSecret, new FailedIconClickHandler())); + this.setListAdapter(new ConversationAdapter(getActivity(), masterSecret, + new FailedIconClickHandler(), + !this.recipients.isSingleRecipient())); getListView().setRecyclerListener((ConversationAdapter)getListAdapter()); getLoaderManager().initLoader(0, null, this); } diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java index 980959c3a3..ae5682c891 100644 --- a/src/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/ConversationItem.java @@ -73,6 +73,7 @@ public class ConversationItem extends LinearLayout { private Handler failedIconHandler; private MessageRecord messageRecord; private MasterSecret masterSecret; + private boolean groupThread; private TextView bodyText; private TextView dateText; @@ -125,11 +126,13 @@ public class ConversationItem extends LinearLayout { 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.masterSecret = masterSecret; this.failedIconHandler = failedIconHandler; + this.groupThread = groupThread; setBodyText(messageRecord); setStatusIcons(messageRecord); @@ -201,19 +204,12 @@ public class ConversationItem extends LinearLayout { } private void setGroupMessageStatus(MessageRecord messageRecord) { -// GroupData groupData = messageRecord.getGroupData(); -// -// if (groupData != null) { -// String status = String.format("Sent (%d/%d)", groupData.groupSentCount, groupData.groupSize); -// -// 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 { + if (groupThread && !messageRecord.isOutgoing()) { + this.groupStatusText.setText(messageRecord.getIndividualRecipient().toShortString()); + this.groupStatusText.setVisibility(View.VISIBLE); + } else { this.groupStatusText.setVisibility(View.GONE); -// } + } } private void setNotificationMmsAttributes(NotificationMmsMessageRecord messageRecord) { @@ -242,6 +238,8 @@ public class ConversationItem extends LinearLayout { if (messageRecord.getPartCount() > 0) { mmsThumbnail.setVisibility(View.VISIBLE); mmsThumbnail.setImageDrawable(new ColorDrawable(Color.TRANSPARENT)); + } else { + mmsThumbnail.setVisibility(View.GONE); } slideDeck = messageRecord.getSlideDeck(); diff --git a/src/org/thoughtcrime/securesms/database/ContentValuesBuilder.java b/src/org/thoughtcrime/securesms/database/ContentValuesBuilder.java index 3d4ba41f14..73170e6881 100644 --- a/src/org/thoughtcrime/securesms/database/ContentValuesBuilder.java +++ b/src/org/thoughtcrime/securesms/database/ContentValuesBuilder.java @@ -19,6 +19,8 @@ package org.thoughtcrime.securesms.database; import android.content.ContentValues; 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.EncodedStringValue; @@ -34,14 +36,14 @@ public class ContentValuesBuilder { public void add(String key, String charsetKey, EncodedStringValue value) { if (value != null) { - contentValues.put(key, toIsoString(value.getTextString())); + contentValues.put(key, Util.toIsoString(value.getTextString())); contentValues.put(charsetKey, value.getCharacterSet()); } } public void add(String contentKey, byte[] value) { if (value != null) { - contentValues.put(contentKey, toIsoString(value)); + contentValues.put(contentKey, Util.toIsoString(value)); } } @@ -58,14 +60,4 @@ public class ContentValuesBuilder { public ContentValues getContentValues() { 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 ""; - } - } - } diff --git a/src/org/thoughtcrime/securesms/database/DatabaseFactory.java b/src/org/thoughtcrime/securesms/database/DatabaseFactory.java index 65a2f392d5..4828da34e4 100644 --- a/src/org/thoughtcrime/securesms/database/DatabaseFactory.java +++ b/src/org/thoughtcrime/securesms/database/DatabaseFactory.java @@ -44,7 +44,8 @@ public class DatabaseFactory { private static final int INTRODUCED_DRAFTS_VERSION = 5; private static final int INTRODUCED_NEW_TYPES_VERSION = 6; 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 Object lock = new Object(); @@ -213,10 +214,14 @@ public class DatabaseFactory { listener.setProgress(smsCursor.getCount() + threadCursor.getPosition(), count); 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 id = threadCursor.getLong(threadCursor.getColumnIndexOrThrow("_id")); + if (!Util.isEmpty(snippet)) { + snippet = masterCipher.decryptBody(snippet); + } + if (snippet.startsWith(KEY_EXCHANGE)) { snippet = snippet.substring(KEY_EXCHANGE.length()); snippet = masterCipher.encryptBody(snippet); @@ -348,6 +353,8 @@ public class DatabaseFactory { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.beginTransaction(); + if (oldVersion < INTRODUCED_IDENTITIES_VERSION) { 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) { - db.beginTransaction(); db.execSQL("ALTER TABLE sms ADD COLUMN date_sent INTEGER;"); db.execSQL("UPDATE sms SET date_sent = date;"); db.execSQL("ALTER TABLE mms ADD COLUMN date_received INTEGER;"); db.execSQL("UPDATE mms SET date_received = date;"); - db.setTransactionSuccessful(); - db.endTransaction(); } if (oldVersion < INTRODUCED_DRAFTS_VERSION) { - db.beginTransaction(); db.execSQL("CREATE TABLE drafts (_id INTEGER PRIMARY KEY, thread_id INTEGER, type TEXT, value TEXT);"); executeStatements(db, new String[] { "CREATE INDEX IF NOT EXISTS draft_thread_index ON drafts (thread_id);", }); - db.setTransactionSuccessful(); - db.endTransaction(); } if (oldVersion < INTRODUCED_NEW_TYPES_VERSION) { @@ -405,7 +406,6 @@ public class DatabaseFactory { String PROCESSED_KEY_EXCHANGE = "?TextSecureKeyExchangd"; String STALE_KEY_EXCHANGE = "?TextSecureKeyExchangs"; - db.beginTransaction(); // SMS Updates db.execSQL("UPDATE sms SET type = ? WHERE type = ?", new String[] {20L+"", 1L+""}); 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); + if (cursor != null) + cursor.close(); + cursor = db.query("sms", null,"body LIKE ?", new String[] {ASYMMETRIC_LOCAL_ENCRYPT + "%"}, null, null, null); updateSmsBodyAndType(db, cursor, ASYMMETRIC_LOCAL_ENCRYPT, 0x40000000L); + if (cursor != null) + cursor.close(); + cursor = db.query("sms", null,"body LIKE ?", new String[] {ASYMMETRIC_ENCRYPT + "%"}, null, null, null); updateSmsBodyAndType(db, cursor, ASYMMETRIC_ENCRYPT, 0L); + if (cursor != null) + cursor.close(); + cursor = db.query("sms", null,"body LIKE ?", new String[] {KEY_EXCHANGE + "%"}, null, null, null); updateSmsBodyAndType(db, cursor, KEY_EXCHANGE, 0x8000L); + if (cursor != null) + cursor.close(); + cursor = db.query("sms", null,"body LIKE ?", new String[] {PROCESSED_KEY_EXCHANGE + "%"}, null, null, null); 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 + "%"}, null, null, null); @@ -468,34 +483,68 @@ public class DatabaseFactory { db.execSQL("ALTER TABLE thread ADD COLUMN snippet_type INTEGER;"); + if (cursor != null) + cursor.close(); + cursor = db.query("thread", null,"snippet LIKE ?", new String[] {SYMMETRIC_ENCRYPT + "%"}, null, null, null); updateThreadSnippetAndType(db, cursor, SYMMETRIC_ENCRYPT, 0x80000000L); + if (cursor != null) + cursor.close(); + cursor = db.query("thread", null,"snippet LIKE ?", new String[] {KEY_EXCHANGE + "%"}, null, null, null); updateThreadSnippetAndType(db, cursor, KEY_EXCHANGE, 0x8000L); + if (cursor != null) + cursor.close(); + cursor = db.query("thread", null,"snippet LIKE ?", new String[] {STALE_KEY_EXCHANGE + "%"}, null, null, null); updateThreadSnippetAndType(db, cursor, STALE_KEY_EXCHANGE, 0x8000L | 0x4000L); + if (cursor != null) + cursor.close(); + cursor = db.query("thread", null,"snippet LIKE ?", new String[] {PROCESSED_KEY_EXCHANGE + "%"}, null, null, null); updateThreadSnippetAndType(db, cursor, KEY_EXCHANGE, 0x8000L | 0x2000L); - db.setTransactionSuccessful(); - db.endTransaction(); + if (cursor != null) + cursor.close(); } if (oldVersion < INTRODUCED_MMS_BODY_VERSION) { db.execSQL("ALTER TABLE mms ADD COLUMN body TEXT"); 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) diff --git a/src/org/thoughtcrime/securesms/database/MmsDatabase.java b/src/org/thoughtcrime/securesms/database/MmsDatabase.java index 3db25ec0a2..3aa2924307 100644 --- a/src/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord; import org.thoughtcrime.securesms.mms.PartParser; import org.thoughtcrime.securesms.mms.SlideDeck; +import org.thoughtcrime.securesms.mms.TextSlide; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientFactory; 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 SUBJECT = "sub"; private static final String SUBJECT_CHARSET = "sub_cs"; - private static final String CONTENT_TYPE = "ct_t"; - private static final String CONTENT_LOCATION = "ct_l"; - private static final String EXPIRY = "exp"; + static final String CONTENT_TYPE = "ct_t"; + static final String CONTENT_LOCATION = "ct_l"; + static final String EXPIRY = "exp"; private static final String MESSAGE_CLASS = "m_cls"; public static final String MESSAGE_TYPE = "m_type"; 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 READ_REPORT = "rr"; private static final String REPORT_ALLOWED = "rpt_a"; private static final String RESPONSE_STATUS = "resp_st"; - private static final String STATUS = "st"; - private static final String TRANSACTION_ID = "tr_id"; + static final String STATUS = "st"; + static final String TRANSACTION_ID = "tr_id"; private static final String RETRIEVE_STATUS = "retr_st"; private static final String RETRIEVE_TEXT = "retr_txt"; 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, " + READ + " INTEGER DEFAULT 0, " + MESSAGE_ID + " TEXT, " + SUBJECT + " TEXT, " + 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, " + MMS_VERSION + " INTEGER, " + MESSAGE_SIZE + " INTEGER, " + PRIORITY + " 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, MESSAGE_SIZE, PRIORITY, REPORT_ALLOWED, STATUS, TRANSACTION_ID, RETRIEVE_STATUS, 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(); @@ -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) { SQLiteDatabase database = databaseHelper.getWritableDatabase(); 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+""}); } - public NotificationInd getNotificationMessage(long messageId) throws MmsException { - PduHeaders headers = getHeadersForId(messageId); - return new NotificationInd(headers); - } - - private MultimediaMessagePdu getMediaMessage(long messageId) + public SendReq[] getOutgoingMessages(MasterSecret masterSecret, long messageId) throws MmsException { - PduHeaders headers = getHeadersForId(messageId); - PartDatabase partDatabase = getPartDatabase(null); - PduBody body = partDatabase.getParts(messageId, false); - - return new MultimediaMessagePdu(headers, body); - } - - public SendReq getSendRequest(MasterSecret masterSecret, long messageId) throws MmsException { - PduHeaders headers = getHeadersForId(messageId); - PartDatabase partDatabase = getPartDatabase(masterSecret); - PduBody body = partDatabase.getParts(messageId, true); - - return new SendReq(headers, body, messageId, headers.getMessageBox()); - } - - public SendReq[] getOutgoingMessages(MasterSecret masterSecret) throws MmsException { - MmsAddressDatabase addr = DatabaseFactory.getMmsAddressDatabase(context); - PartDatabase parts = getPartDatabase(masterSecret); - SQLiteDatabase database = databaseHelper.getReadableDatabase(); - Cursor cursor = null; + MmsAddressDatabase addr = DatabaseFactory.getMmsAddressDatabase(context); + PartDatabase parts = getPartDatabase(masterSecret); + SQLiteDatabase database = databaseHelper.getReadableDatabase(); + MasterCipher masterCipher = masterSecret == null ? null : new MasterCipher(masterSecret); + Cursor cursor = null; + + + String selection; + String[] selectionArgs; + + if (messageId > 0) { + selection = ID_WHERE; + selectionArgs = new String[]{messageId + ""}; + } else { + selection = MESSAGE_BOX + " & " + Types.BASE_TYPE_MASK + " = ?"; + selectionArgs = new String[]{Types.BASE_OUTBOX_TYPE + ""}; + } try { - cursor = database.query(TABLE_NAME, MMS_PROJECTION, - MESSAGE_BOX + " & " + Types.BASE_TYPE_MASK + " = ?", - new String[] {Types.BASE_OUTBOX_TYPE+""}, - null, null, null); + cursor = database.query(TABLE_NAME, MMS_PROJECTION, selection, selectionArgs, null, null, null); if (cursor == null || cursor.getCount() == 0) return new SendReq[0]; @@ -337,12 +298,25 @@ public class MmsDatabase extends Database implements MmsSmsColumns { int i = 0; while (cursor.moveToNext()) { - long messageId = cursor.getLong(cursor.getColumnIndexOrThrow(ID)); + messageId = cursor.getLong(cursor.getColumnIndexOrThrow(ID)); 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); 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; @@ -467,6 +441,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns { contentValues.put(THREAD_ID, threadId); contentValues.put(READ, 1); contentValues.put(DATE_RECEIVED, contentValues.getAsLong(DATE_SENT)); + contentValues.remove(ADDRESS); long messageId = insertMediaMessage(masterSecret, sendRequest, contentValues); 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); @@ -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 { PduHeaders headers = new PduHeaders(); 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(EXPIRY, headers.getLongInteger(PduHeaders.EXPIRY)); cvb.add(MESSAGE_SIZE, headers.getLongInteger(PduHeaders.MESSAGE_SIZE)); + cvb.add(ADDRESS, headers.getEncodedStringValue(PduHeaders.FROM).getTextString()); 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) { 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 box = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX)); long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.THREAD_ID)); + String address = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS)); DisplayRecord.Body body = getBody(cursor); int partCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.PART_COUNT)); - Recipient recipient = getMessageRecipient(id); + Recipients recipients = getRecipientsFor(address); ListenableFutureTask 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, 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) { try { String body = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.BODY)); @@ -800,17 +804,11 @@ public class MmsDatabase extends Database implements MmsSmsColumns { Callable task = new Callable() { @Override public SlideDeck call() throws Exception { - try { - if (masterSecret == null) - return null; - - MultimediaMessagePdu pdu = getMediaMessage(id); - - return new SlideDeck(context, masterSecret, pdu.getBody()); - } catch (MmsException me) { - Log.w("MmsDatabase", me); + if (masterSecret == 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; } - 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() { cursor.close(); } diff --git a/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java b/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java index 94d7214a20..d439026235 100644 --- a/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java +++ b/src/org/thoughtcrime/securesms/database/MmsSmsColumns.java @@ -8,6 +8,8 @@ public interface MmsSmsColumns { public static final String THREAD_ID = "thread_id"; public static final String READ = "read"; public static final String BODY = "body"; + public static final String ADDRESS = "address"; + public static class Types { protected static final long TOTAL_MASK = 0xFFFFFFFF; diff --git a/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java b/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java index 92ec5d6332..a0298b2dc8 100644 --- a/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/MmsSmsDatabase.java @@ -39,54 +39,6 @@ public class MmsSmsDatabase extends Database { 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) { String[] projection = {MmsSmsColumns.ID, SmsDatabase.BODY, SmsDatabase.TYPE, MmsSmsColumns.THREAD_ID, @@ -94,7 +46,10 @@ public class MmsSmsDatabase extends Database { MmsSmsColumns.NORMALIZED_DATE_SENT, MmsSmsColumns.NORMALIZED_DATE_RECEIVED, 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"; @@ -113,7 +68,11 @@ public class MmsSmsDatabase extends Database { MmsSmsColumns.NORMALIZED_DATE_SENT, MmsSmsColumns.NORMALIZED_DATE_RECEIVED, 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 selection = MmsSmsColumns.THREAD_ID + " = " + threadId; @@ -127,7 +86,11 @@ public class MmsSmsDatabase extends Database { MmsSmsColumns.NORMALIZED_DATE_SENT, MmsSmsColumns.NORMALIZED_DATE_RECEIVED, 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 selection = MmsSmsColumns.READ + " = 0"; @@ -146,13 +109,19 @@ public class MmsSmsDatabase extends Database { MmsDatabase.DATE_RECEIVED + " * 1000 AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED, MmsSmsColumns.ID, SmsDatabase.BODY, MmsSmsColumns.READ, MmsSmsColumns.THREAD_ID, 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, SmsDatabase.DATE_RECEIVED + " * 1 AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED, MmsSmsColumns.ID, SmsDatabase.BODY, MmsSmsColumns.READ, MmsSmsColumns.THREAD_ID, 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(); @@ -166,25 +135,31 @@ public class MmsSmsDatabase extends Database { Set mmsColumnsPresent = new HashSet(); 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_BOX); mmsColumnsPresent.add(MmsDatabase.DATE_SENT); 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.CONTENT_LOCATION); + mmsColumnsPresent.add(MmsDatabase.TRANSACTION_ID); + mmsColumnsPresent.add(MmsDatabase.MESSAGE_SIZE); + mmsColumnsPresent.add(MmsDatabase.EXPIRY); + mmsColumnsPresent.add(MmsDatabase.STATUS); Set smsColumnsPresent = new HashSet(); smsColumnsPresent.add(MmsSmsColumns.ID); smsColumnsPresent.add(MmsSmsColumns.BODY); + smsColumnsPresent.add(MmsSmsColumns.ADDRESS); + smsColumnsPresent.add(MmsSmsColumns.READ); + smsColumnsPresent.add(MmsSmsColumns.THREAD_ID); smsColumnsPresent.add(SmsDatabase.TYPE); - smsColumnsPresent.add(SmsDatabase.ADDRESS); smsColumnsPresent.add(SmsDatabase.SUBJECT); smsColumnsPresent.add(SmsDatabase.DATE_SENT); smsColumnsPresent.add(SmsDatabase.DATE_RECEIVED); - smsColumnsPresent.add(MmsSmsColumns.READ); - smsColumnsPresent.add(MmsSmsColumns.THREAD_ID); smsColumnsPresent.add(SmsDatabase.STATUS); String mmsSubQuery = mmsQueryBuilder.buildUnionSubQuery(TRANSPORT, mmsProjection, mmsColumnsPresent, 2, MMS_TRANSPORT, selection, null, null, null); diff --git a/src/org/thoughtcrime/securesms/database/SmsDatabase.java b/src/org/thoughtcrime/securesms/database/SmsDatabase.java index 9d3890608c..f8903e575f 100644 --- a/src/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -52,7 +52,6 @@ import java.util.Set; public class SmsDatabase extends Database implements MmsSmsColumns { public static final String TABLE_NAME = "sms"; - public static final String ADDRESS = "address"; public static final String PERSON = "person"; static final String DATE_RECEIVED = "date"; 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 REPLY_PATH_PRESENT = "reply_path_present"; public static final String SUBJECT = "subject"; -//public static final String BODY = "body"; public static final String SERVICE_CENTER = "service_center"; public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " integer PRIMARY KEY, " + diff --git a/src/org/thoughtcrime/securesms/database/model/MediaMmsMessageRecord.java b/src/org/thoughtcrime/securesms/database/model/MediaMmsMessageRecord.java index 979b49f9ab..cf7127ade4 100644 --- a/src/org/thoughtcrime/securesms/database/model/MediaMmsMessageRecord.java +++ b/src/org/thoughtcrime/securesms/database/model/MediaMmsMessageRecord.java @@ -75,7 +75,7 @@ public class MediaMmsMessageRecord extends MessageRecord { return emphasisAdded(context.getString(R.string.MmsMessageRecord_bad_encrypted_mms_message)); } else if (MmsDatabase.Types.isNoRemoteSessionType(type)) { 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)); } diff --git a/src/org/thoughtcrime/securesms/mms/PartParser.java b/src/org/thoughtcrime/securesms/mms/PartParser.java index fad3bea7a1..b152075a40 100644 --- a/src/org/thoughtcrime/securesms/mms/PartParser.java +++ b/src/org/thoughtcrime/securesms/mms/PartParser.java @@ -44,4 +44,21 @@ public class PartParser { return stripped; } + + public static int getDisplayablePartCount(PduBody body) { + int partCount = 0; + + for (int i=0;i sendRequests; - - if (messageId == -1) { - sendRequests = Arrays.asList(database.getOutgoingMessages(masterSecret)); - } else { - sendRequests = new ArrayList(1); - sendRequests.add(database.getSendRequest(masterSecret, messageId)); - } - - return sendRequests; + return Arrays.asList(database.getOutgoingMessages(masterSecret, messageId)); } protected void handleConnectivityChange() {