2012-09-08 03:03:23 +00:00
|
|
|
/**
|
2011-12-20 18:20:44 +00:00
|
|
|
* Copyright (C) 2011 Whisper Systems
|
2012-09-08 03:03:23 +00:00
|
|
|
*
|
2011-12-20 18:20:44 +00:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2012-09-08 03:03:23 +00:00
|
|
|
*
|
2011-12-20 18:20:44 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
package org.thoughtcrime.securesms.database;
|
|
|
|
|
2012-09-08 03:03:23 +00:00
|
|
|
import android.content.ContentValues;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.database.Cursor;
|
|
|
|
import android.database.sqlite.SQLiteDatabase;
|
|
|
|
import android.database.sqlite.SQLiteOpenHelper;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.util.Log;
|
2013-04-26 18:23:43 +00:00
|
|
|
import android.util.Pair;
|
2011-12-20 18:20:44 +00:00
|
|
|
|
2012-09-08 03:03:23 +00:00
|
|
|
import org.thoughtcrime.securesms.R;
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
import org.thoughtcrime.securesms.contacts.ContactPhotoFactory;
|
2013-04-26 18:23:43 +00:00
|
|
|
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
2013-04-30 18:14:01 +00:00
|
|
|
import org.thoughtcrime.securesms.database.model.DisplayRecord;
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
|
|
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
|
|
|
import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord;
|
2013-04-26 18:23:43 +00:00
|
|
|
import org.thoughtcrime.securesms.mms.PartParser;
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
2013-05-05 19:51:36 +00:00
|
|
|
import org.thoughtcrime.securesms.mms.TextSlide;
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
2011-12-20 18:20:44 +00:00
|
|
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
|
|
|
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
|
|
|
import org.thoughtcrime.securesms.recipients.Recipients;
|
2013-04-26 18:23:43 +00:00
|
|
|
import org.thoughtcrime.securesms.util.InvalidMessageException;
|
2013-05-06 19:22:03 +00:00
|
|
|
import org.thoughtcrime.securesms.util.LRUCache;
|
2013-04-26 18:23:43 +00:00
|
|
|
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
2013-01-10 05:06:56 +00:00
|
|
|
import org.thoughtcrime.securesms.util.Trimmer;
|
2013-02-27 06:55:23 +00:00
|
|
|
import org.thoughtcrime.securesms.util.Util;
|
2011-12-20 18:20:44 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
import java.io.UnsupportedEncodingException;
|
2013-05-06 19:22:03 +00:00
|
|
|
import java.lang.ref.SoftReference;
|
|
|
|
import java.util.Collections;
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
import java.util.HashSet;
|
2013-05-06 19:22:03 +00:00
|
|
|
import java.util.Map;
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
import java.util.Set;
|
2013-04-26 18:23:43 +00:00
|
|
|
import java.util.concurrent.Callable;
|
|
|
|
import java.util.concurrent.ExecutorService;
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
import ws.com.google.android.mms.InvalidHeaderValueException;
|
|
|
|
import ws.com.google.android.mms.MmsException;
|
|
|
|
import ws.com.google.android.mms.pdu.CharacterSets;
|
|
|
|
import ws.com.google.android.mms.pdu.EncodedStringValue;
|
|
|
|
import ws.com.google.android.mms.pdu.MultimediaMessagePdu;
|
|
|
|
import ws.com.google.android.mms.pdu.NotificationInd;
|
|
|
|
import ws.com.google.android.mms.pdu.PduBody;
|
|
|
|
import ws.com.google.android.mms.pdu.PduHeaders;
|
|
|
|
import ws.com.google.android.mms.pdu.RetrieveConf;
|
|
|
|
import ws.com.google.android.mms.pdu.SendReq;
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
// XXXX Clean up MMS efficiency:
|
|
|
|
// 1) We need to be careful about how much memory we're using for parts. SoftRefereences.
|
|
|
|
// 2) How many queries do we make? calling getMediaMessageForId() from within an existing query
|
|
|
|
// seems wasteful.
|
2011-12-20 18:20:44 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public class MmsDatabase extends Database implements MmsSmsColumns {
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public static final String TABLE_NAME = "mms";
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
static final String DATE_SENT = "date";
|
|
|
|
static final String DATE_RECEIVED = "date_received";
|
2011-12-20 18:20:44 +00:00
|
|
|
public static final String MESSAGE_BOX = "msg_box";
|
|
|
|
private static final String MESSAGE_ID = "m_id";
|
|
|
|
private static final String SUBJECT = "sub";
|
|
|
|
private static final String SUBJECT_CHARSET = "sub_cs";
|
2013-05-05 19:51:36 +00:00
|
|
|
static final String CONTENT_TYPE = "ct_t";
|
|
|
|
static final String CONTENT_LOCATION = "ct_l";
|
|
|
|
static final String EXPIRY = "exp";
|
2011-12-20 18:20:44 +00:00
|
|
|
private static final String MESSAGE_CLASS = "m_cls";
|
|
|
|
public static final String MESSAGE_TYPE = "m_type";
|
|
|
|
private static final String MMS_VERSION = "v";
|
2013-05-05 19:51:36 +00:00
|
|
|
static final String MESSAGE_SIZE = "m_size";
|
2011-12-20 18:20:44 +00:00
|
|
|
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";
|
2013-05-05 19:51:36 +00:00
|
|
|
static final String STATUS = "st";
|
|
|
|
static final String TRANSACTION_ID = "tr_id";
|
2011-12-20 18:20:44 +00:00
|
|
|
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";
|
|
|
|
private static final String READ_STATUS = "read_status";
|
|
|
|
private static final String CONTENT_CLASS = "ct_cls";
|
|
|
|
private static final String RESPONSE_TEXT = "resp_txt";
|
|
|
|
private static final String DELIVERY_TIME = "d_tm";
|
|
|
|
private static final String DELIVERY_REPORT = "d_rpt";
|
2013-04-26 18:23:43 +00:00
|
|
|
static final String PART_COUNT = "part_count";
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
|
2013-01-07 02:47:20 +00:00
|
|
|
THREAD_ID + " INTEGER, " + DATE_SENT + " INTEGER, " + DATE_RECEIVED + " INTEGER, " + MESSAGE_BOX + " INTEGER, " +
|
2011-12-20 18:20:44 +00:00
|
|
|
READ + " INTEGER DEFAULT 0, " + MESSAGE_ID + " TEXT, " + SUBJECT + " TEXT, " +
|
2013-04-26 18:23:43 +00:00
|
|
|
SUBJECT_CHARSET + " INTEGER, " + BODY + " TEXT, " + PART_COUNT + " INTEGER, " +
|
2013-05-05 19:51:36 +00:00
|
|
|
CONTENT_TYPE + " TEXT, " + CONTENT_LOCATION + " TEXT, " + ADDRESS + " TEXT, " +
|
2011-12-20 18:20:44 +00:00
|
|
|
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, " +
|
|
|
|
STATUS + " INTEGER, " + TRANSACTION_ID + " TEXT, " + RETRIEVE_STATUS + " INTEGER, " +
|
2012-09-08 03:03:23 +00:00
|
|
|
RETRIEVE_TEXT + " TEXT, " + RETRIEVE_TEXT_CS + " INTEGER, " + READ_STATUS + " INTEGER, " +
|
2011-12-20 18:20:44 +00:00
|
|
|
CONTENT_CLASS + " INTEGER, " + RESPONSE_TEXT + " TEXT, " + DELIVERY_TIME + " INTEGER, " +
|
|
|
|
DELIVERY_REPORT + " INTEGER);";
|
|
|
|
|
2012-10-30 00:41:06 +00:00
|
|
|
public static final String[] CREATE_INDEXS = {
|
|
|
|
"CREATE INDEX IF NOT EXISTS mms_thread_id_index ON " + TABLE_NAME + " (" + THREAD_ID + ");",
|
|
|
|
"CREATE INDEX IF NOT EXISTS mms_read_index ON " + TABLE_NAME + " (" + READ + ");",
|
|
|
|
"CREATE INDEX IF NOT EXISTS mms_read_and_thread_id_index ON " + TABLE_NAME + "(" + READ + "," + THREAD_ID + ");",
|
|
|
|
"CREATE INDEX IF NOT EXISTS mms_message_box_index ON " + TABLE_NAME + " (" + MESSAGE_BOX + ");"
|
|
|
|
};
|
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
private static final String[] MMS_PROJECTION = new String[] {
|
|
|
|
ID, THREAD_ID, DATE_SENT + " * 1000 AS " + NORMALIZED_DATE_SENT,
|
|
|
|
DATE_RECEIVED + " * 1000 AS " + NORMALIZED_DATE_RECEIVED,
|
|
|
|
MESSAGE_BOX, READ, MESSAGE_ID, SUBJECT, SUBJECT_CHARSET, CONTENT_TYPE,
|
|
|
|
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,
|
2013-05-05 19:51:36 +00:00
|
|
|
DELIVERY_TIME, DELIVERY_REPORT, BODY, PART_COUNT, ADDRESS
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
};
|
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
public static final ExecutorService slideResolver = Util.newSingleThreadedLifoExecutor();
|
2013-05-06 19:22:03 +00:00
|
|
|
private static final Map<Long, SoftReference<SlideDeck>> slideCache =
|
|
|
|
Collections.synchronizedMap(new LRUCache<Long, SoftReference<SlideDeck>>(20));
|
2013-04-26 18:23:43 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public MmsDatabase(Context context, SQLiteOpenHelper databaseHelper) {
|
|
|
|
super(context, databaseHelper);
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public int getMessageCountForThread(long threadId) {
|
2012-09-08 03:03:23 +00:00
|
|
|
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
2011-12-20 18:20:44 +00:00
|
|
|
Cursor cursor = null;
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
try {
|
|
|
|
cursor = db.query(TABLE_NAME, new String[] {"COUNT(*)"}, THREAD_ID + " = ?", new String[] {threadId+""}, null, null, null);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
if (cursor != null && cursor.moveToFirst())
|
|
|
|
return cursor.getInt(0);
|
|
|
|
} finally {
|
|
|
|
if (cursor != null)
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public long getThreadIdForMessage(long id) {
|
|
|
|
String sql = "SELECT " + THREAD_ID + " FROM " + TABLE_NAME + " WHERE " + ID + " = ?";
|
|
|
|
String[] sqlArgs = new String[] {id+""};
|
|
|
|
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
Cursor cursor = null;
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
try {
|
|
|
|
cursor = db.rawQuery(sql, sqlArgs);
|
|
|
|
if (cursor != null && cursor.moveToFirst())
|
|
|
|
return cursor.getLong(0);
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
} finally {
|
|
|
|
if (cursor != null)
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-04-26 01:59:49 +00:00
|
|
|
private long getThreadIdFor(RetrieveConf retrieved) throws RecipientFormattingException {
|
2011-12-20 18:20:44 +00:00
|
|
|
try {
|
2013-04-26 01:59:49 +00:00
|
|
|
Set<String> group = new HashSet<String>();
|
|
|
|
|
|
|
|
EncodedStringValue encodedFrom = retrieved.getFrom();
|
|
|
|
group.add(new String(encodedFrom.getTextString(), CharacterSets.MIMENAME_ISO_8859_1));
|
|
|
|
|
|
|
|
EncodedStringValue[] encodedCcList = retrieved.getCc();
|
|
|
|
if (encodedCcList != null) {
|
|
|
|
for (EncodedStringValue encodedCc : encodedCcList) {
|
|
|
|
group.add(new String(encodedCc.getTextString(), CharacterSets.MIMENAME_ISO_8859_1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
for (String recipient : group) {
|
|
|
|
sb.append(recipient);
|
|
|
|
sb.append(",");
|
|
|
|
}
|
|
|
|
|
|
|
|
Recipients recipients = RecipientFactory.getRecipientsFromString(context, sb.toString(), false);
|
|
|
|
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
|
|
|
} catch (UnsupportedEncodingException e) {
|
|
|
|
throw new AssertionError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private long getThreadIdFor(NotificationInd notification) throws RecipientFormattingException {
|
|
|
|
try {
|
|
|
|
EncodedStringValue encodedString = notification.getFrom();
|
2011-12-20 18:20:44 +00:00
|
|
|
String fromString = new String(encodedString.getTextString(), CharacterSets.MIMENAME_ISO_8859_1);
|
2012-12-24 16:40:37 +00:00
|
|
|
Recipients recipients = RecipientFactory.getRecipientsFromString(context, fromString, false);
|
2011-12-20 18:20:44 +00:00
|
|
|
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
|
|
|
} catch (UnsupportedEncodingException e) {
|
|
|
|
throw new AssertionError(e);
|
|
|
|
}
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public void updateResponseStatus(long messageId, int status) {
|
|
|
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
|
|
|
ContentValues contentValues = new ContentValues();
|
|
|
|
contentValues.put(RESPONSE_STATUS, status);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-04-30 18:14:01 +00:00
|
|
|
database.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {messageId + ""});
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
private void updateMailboxBitmask(long id, long maskOff, long maskOn) {
|
|
|
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
|
|
|
db.execSQL("UPDATE " + TABLE_NAME +
|
|
|
|
" SET " + MESSAGE_BOX + " = (" + MESSAGE_BOX + " & " + (Types.TOTAL_MASK - maskOff) + " | " + maskOn + " )" +
|
2013-04-30 18:14:01 +00:00
|
|
|
" WHERE " + ID + " = ?", new String[] {id + ""});
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-10-13 10:53:41 +00:00
|
|
|
public void markAsSending(long messageId) {
|
|
|
|
updateMailboxBitmask(messageId, Types.BASE_TYPE_MASK, Types.BASE_SENDING_TYPE);
|
|
|
|
notifyConversationListeners(getThreadIdForMessage(messageId));
|
|
|
|
}
|
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public void markAsSentFailed(long messageId) {
|
|
|
|
updateMailboxBitmask(messageId, Types.BASE_TYPE_MASK, Types.BASE_SENT_FAILED_TYPE);
|
2011-12-20 18:20:44 +00:00
|
|
|
notifyConversationListeners(getThreadIdForMessage(messageId));
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public void markAsSent(long messageId, byte[] mmsId, long status) {
|
2011-12-20 18:20:44 +00:00
|
|
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
|
|
|
ContentValues contentValues = new ContentValues();
|
|
|
|
contentValues.put(RESPONSE_STATUS, status);
|
|
|
|
contentValues.put(MESSAGE_ID, new String(mmsId));
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
database.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {messageId+""});
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
updateMailboxBitmask(messageId, Types.BASE_TYPE_MASK, Types.BASE_SENT_TYPE);
|
2012-09-08 03:03:23 +00:00
|
|
|
notifyConversationListeners(getThreadIdForMessage(messageId));
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public void markDownloadState(long messageId, long state) {
|
|
|
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
|
|
|
ContentValues contentValues = new ContentValues();
|
|
|
|
contentValues.put(STATUS, state);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-04-30 18:14:01 +00:00
|
|
|
database.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {messageId + ""});
|
2012-09-08 03:03:23 +00:00
|
|
|
notifyConversationListeners(getThreadIdForMessage(messageId));
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public void markAsNoSession(long messageId, long threadId) {
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
updateMailboxBitmask(messageId, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_NO_SESSION_BIT);
|
2012-09-08 03:03:23 +00:00
|
|
|
notifyConversationListeners(threadId);
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public void markAsDecryptFailed(long messageId, long threadId) {
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
updateMailboxBitmask(messageId, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_FAILED_BIT);
|
2012-09-08 03:03:23 +00:00
|
|
|
notifyConversationListeners(threadId);
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public void setMessagesRead(long threadId) {
|
|
|
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
|
|
|
ContentValues contentValues = new ContentValues();
|
|
|
|
contentValues.put(READ, 1);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
database.update(TABLE_NAME, contentValues, THREAD_ID + " = ?", new String[] {threadId+""});
|
|
|
|
}
|
|
|
|
|
2013-05-06 20:59:40 +00:00
|
|
|
public void setAllMessagesRead() {
|
|
|
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
|
|
|
ContentValues contentValues = new ContentValues();
|
|
|
|
contentValues.put(READ, 1);
|
|
|
|
|
|
|
|
database.update(TABLE_NAME, contentValues, null, null);
|
|
|
|
}
|
|
|
|
|
2013-05-05 19:51:36 +00:00
|
|
|
public SendReq[] getOutgoingMessages(MasterSecret masterSecret, long messageId)
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
throws MmsException
|
|
|
|
{
|
2013-05-05 19:51:36 +00:00
|
|
|
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 + ""};
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
try {
|
2013-05-05 19:51:36 +00:00
|
|
|
cursor = database.query(TABLE_NAME, MMS_PROJECTION, selection, selectionArgs, null, null, null);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
if (cursor == null || cursor.getCount() == 0)
|
|
|
|
return new SendReq[0];
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
SendReq[] requests = new SendReq[cursor.getCount()];
|
|
|
|
int i = 0;
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
while (cursor.moveToNext()) {
|
2013-05-05 19:51:36 +00:00
|
|
|
messageId = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
2012-10-01 02:56:29 +00:00
|
|
|
long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
|
2013-05-05 19:51:36 +00:00
|
|
|
String messageText = cursor.getString(cursor.getColumnIndexOrThrow(BODY));
|
|
|
|
PduHeaders headers = getHeadersFromCursor(cursor);
|
2012-10-01 02:56:29 +00:00
|
|
|
addr.getAddressesForId(messageId, headers);
|
|
|
|
PduBody body = parts.getParts(messageId, true);
|
2013-05-05 19:51:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
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);
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return requests;
|
|
|
|
} finally {
|
|
|
|
if (cursor != null)
|
|
|
|
cursor.close();
|
2012-09-08 03:03:23 +00:00
|
|
|
}
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
private Pair<Long, Long> insertMessageInbox(MasterSecret masterSecret, RetrieveConf retrieved,
|
|
|
|
String contentLocation, long threadId, long mailbox)
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
throws MmsException
|
|
|
|
{
|
2011-12-20 18:20:44 +00:00
|
|
|
PduHeaders headers = retrieved.getPduHeaders();
|
|
|
|
ContentValues contentValues = getContentValuesFromHeader(headers);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-04-26 01:59:49 +00:00
|
|
|
if (!Util.isEmpty(retrieved.getCc())) {
|
|
|
|
try {
|
|
|
|
threadId = getThreadIdFor(retrieved);
|
|
|
|
} catch (RecipientFormattingException e) {
|
|
|
|
Log.w("MmsDatabase", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
contentValues.put(MESSAGE_BOX, mailbox);
|
|
|
|
contentValues.put(THREAD_ID, threadId);
|
|
|
|
contentValues.put(CONTENT_LOCATION, contentLocation);
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
contentValues.put(STATUS, Status.DOWNLOAD_INITIALIZED);
|
2013-01-06 21:13:14 +00:00
|
|
|
contentValues.put(DATE_RECEIVED, System.currentTimeMillis() / 1000);
|
|
|
|
|
|
|
|
if (!contentValues.containsKey(DATE_SENT))
|
|
|
|
contentValues.put(DATE_SENT, contentValues.getAsLong(DATE_RECEIVED));
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
long messageId = insertMediaMessage(masterSecret, retrieved, contentValues);
|
|
|
|
|
|
|
|
DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
|
2013-05-05 20:14:23 +00:00
|
|
|
DatabaseFactory.getThreadDatabase(context).update(threadId);
|
|
|
|
notifyConversationListeners(threadId);
|
2013-04-26 18:23:43 +00:00
|
|
|
Trimmer.trimThread(context, threadId);
|
|
|
|
|
2013-05-05 20:14:23 +00:00
|
|
|
return new Pair<Long, Long>(messageId, threadId);
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
public Pair<Long, Long> insertMessageInbox(MasterSecret masterSecret, RetrieveConf retrieved,
|
|
|
|
String contentLocation, long threadId)
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
throws MmsException
|
|
|
|
{
|
|
|
|
return insertMessageInbox(masterSecret, retrieved, contentLocation, threadId,
|
|
|
|
Types.BASE_INBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT);
|
2012-09-08 03:03:23 +00:00
|
|
|
}
|
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
public Pair<Long, Long> insertSecureMessageInbox(MasterSecret masterSecret, RetrieveConf retrieved,
|
|
|
|
String contentLocation, long threadId)
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
throws MmsException
|
|
|
|
{
|
|
|
|
return insertMessageInbox(masterSecret, retrieved, contentLocation, threadId,
|
|
|
|
Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT | Types.ENCRYPTION_REMOTE_BIT);
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
public Pair<Long, Long> insertSecureDecryptedMessageInbox(MasterSecret masterSecret,
|
|
|
|
RetrieveConf retrieved,
|
|
|
|
long threadId)
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
throws MmsException
|
|
|
|
{
|
|
|
|
return insertMessageInbox(masterSecret, retrieved, "", threadId,
|
|
|
|
Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT | Types.ENCRYPTION_SYMMETRIC_BIT);
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
public Pair<Long, Long> insertMessageInbox(NotificationInd notification) {
|
2011-12-20 18:20:44 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
|
|
|
PduHeaders headers = notification.getPduHeaders();
|
|
|
|
ContentValues contentValues = getContentValuesFromHeader(headers);
|
2013-04-26 01:59:49 +00:00
|
|
|
long threadId = getThreadIdFor(notification);
|
2011-12-20 18:20:44 +00:00
|
|
|
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
Log.w("MmsDatabse", "Message received type: " + headers.getOctet(PduHeaders.MESSAGE_TYPE));
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
contentValues.put(MESSAGE_BOX, Types.BASE_INBOX_TYPE);
|
2011-12-20 18:20:44 +00:00
|
|
|
contentValues.put(THREAD_ID, threadId);
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
contentValues.put(STATUS, Status.DOWNLOAD_INITIALIZED);
|
2013-01-06 21:13:14 +00:00
|
|
|
contentValues.put(DATE_RECEIVED, System.currentTimeMillis() / 1000);
|
|
|
|
|
|
|
|
if (!contentValues.containsKey(DATE_SENT))
|
|
|
|
contentValues.put(DATE_SENT, contentValues.getAsLong(DATE_RECEIVED));
|
2012-09-08 03:03:23 +00:00
|
|
|
|
|
|
|
long messageId = db.insert(TABLE_NAME, null, contentValues);
|
2011-12-20 18:20:44 +00:00
|
|
|
addressDatabase.insertAddressesForId(messageId, headers);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
// notifyConversationListeners(threadId);
|
|
|
|
// DatabaseFactory.getThreadDatabase(context).update(threadId);
|
|
|
|
// DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
|
|
|
|
// Trimmer.trimThread(context, threadId);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
return new Pair<Long, Long>(messageId, threadId);
|
2011-12-20 18:20:44 +00:00
|
|
|
} catch (RecipientFormattingException rfe) {
|
|
|
|
Log.w("MmsDatabase", rfe);
|
2013-04-26 18:23:43 +00:00
|
|
|
return new Pair<Long, Long>(-1L, -1L);
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
public void markIncomingNotificationReceived(long threadId) {
|
|
|
|
notifyConversationListeners(threadId);
|
|
|
|
DatabaseFactory.getThreadDatabase(context).update(threadId);
|
|
|
|
DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
|
|
|
|
Trimmer.trimThread(context, threadId);
|
|
|
|
}
|
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public long insertMessageOutbox(MasterSecret masterSecret, SendReq sendRequest,
|
|
|
|
long threadId, boolean isSecure)
|
|
|
|
throws MmsException
|
|
|
|
{
|
2013-04-26 18:23:43 +00:00
|
|
|
long type = Types.BASE_OUTBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT;
|
2011-12-20 18:20:44 +00:00
|
|
|
PduHeaders headers = sendRequest.getPduHeaders();
|
|
|
|
ContentValues contentValues = getContentValuesFromHeader(headers);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
if (isSecure) {
|
|
|
|
type |= Types.SECURE_MESSAGE_BIT;
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
contentValues.put(MESSAGE_BOX, type);
|
2011-12-20 18:20:44 +00:00
|
|
|
contentValues.put(THREAD_ID, threadId);
|
|
|
|
contentValues.put(READ, 1);
|
2013-01-06 21:13:14 +00:00
|
|
|
contentValues.put(DATE_RECEIVED, contentValues.getAsLong(DATE_SENT));
|
2013-05-05 19:51:36 +00:00
|
|
|
contentValues.remove(ADDRESS);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
long messageId = insertMediaMessage(masterSecret, sendRequest, contentValues);
|
2013-01-10 05:06:56 +00:00
|
|
|
Trimmer.trimThread(context, threadId);
|
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
return messageId;
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
private long insertMediaMessage(MasterSecret masterSecret,
|
|
|
|
MultimediaMessagePdu message,
|
|
|
|
ContentValues contentValues)
|
|
|
|
throws MmsException
|
|
|
|
{
|
2011-12-20 18:20:44 +00:00
|
|
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
PartDatabase partsDatabase = getPartDatabase(masterSecret);
|
2011-12-20 18:20:44 +00:00
|
|
|
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
2013-04-26 18:23:43 +00:00
|
|
|
PduBody body = message.getBody();
|
|
|
|
|
|
|
|
if (Types.isSymmetricEncryption(contentValues.getAsLong(MESSAGE_BOX))) {
|
|
|
|
String messageText = PartParser.getMessageText(body);
|
|
|
|
body = PartParser.getNonTextParts(body);
|
|
|
|
|
|
|
|
if (!Util.isEmpty(messageText)) {
|
|
|
|
contentValues.put(BODY, new MasterCipher(masterSecret).encryptBody(messageText));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-05 19:51:36 +00:00
|
|
|
contentValues.put(PART_COUNT, PartParser.getDisplayablePartCount(body));
|
2013-04-26 18:23:43 +00:00
|
|
|
|
|
|
|
long messageId = db.insert(TABLE_NAME, null, contentValues);
|
2011-12-20 18:20:44 +00:00
|
|
|
|
|
|
|
addressDatabase.insertAddressesForId(messageId, message.getPduHeaders());
|
|
|
|
partsDatabase.insertParts(messageId, body);
|
|
|
|
|
|
|
|
notifyConversationListeners(contentValues.getAsLong(THREAD_ID));
|
|
|
|
DatabaseFactory.getThreadDatabase(context).update(contentValues.getAsLong(THREAD_ID));
|
|
|
|
|
2012-09-08 03:03:23 +00:00
|
|
|
return messageId;
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public void delete(long messageId) {
|
|
|
|
long threadId = getThreadIdForMessage(messageId);
|
|
|
|
MmsAddressDatabase addrDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
|
|
|
PartDatabase partDatabase = DatabaseFactory.getPartDatabase(context);
|
|
|
|
partDatabase.deleteParts(messageId);
|
|
|
|
addrDatabase.deleteAddressesForId(messageId);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
|
|
|
database.delete(TABLE_NAME, ID_WHERE, new String[] {messageId+""});
|
|
|
|
DatabaseFactory.getThreadDatabase(context).update(threadId);
|
|
|
|
notifyConversationListeners(threadId);
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public void deleteThread(long threadId) {
|
|
|
|
Set<Long> singleThreadSet = new HashSet<Long>();
|
|
|
|
singleThreadSet.add(threadId);
|
|
|
|
deleteThreads(singleThreadSet);
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
/*package*/ void deleteThreads(Set<Long> threadIds) {
|
|
|
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
|
|
|
String where = "";
|
|
|
|
Cursor cursor = null;
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
for (long threadId : threadIds) {
|
|
|
|
where += THREAD_ID + " = '" + threadId + "' OR ";
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
where = where.substring(0, where.length() - 4);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
try {
|
|
|
|
cursor = db.query(TABLE_NAME, new String[] {ID}, where, null, null, null, null);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
while (cursor != null && cursor.moveToNext()) {
|
|
|
|
delete(cursor.getLong(0));
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
} finally {
|
|
|
|
if (cursor != null)
|
|
|
|
cursor.close();
|
2012-09-08 03:03:23 +00:00
|
|
|
}
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
|
|
|
|
2013-01-10 05:06:56 +00:00
|
|
|
/*package*/void deleteMessagesInThreadBeforeDate(long threadId, long date) {
|
|
|
|
date = date / 1000;
|
|
|
|
Cursor cursor = null;
|
|
|
|
|
|
|
|
try {
|
|
|
|
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
String where = THREAD_ID + " = ? AND (CASE (" + MESSAGE_BOX + " & " + Types.BASE_TYPE_MASK + ") ";
|
2013-01-10 05:06:56 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
for (long outgoingType : Types.OUTGOING_MESSAGE_TYPES) {
|
2013-01-10 05:06:56 +00:00
|
|
|
where += " WHEN " + outgoingType + " THEN " + DATE_SENT + " < " + date;
|
|
|
|
}
|
|
|
|
|
|
|
|
where += (" ELSE " + DATE_RECEIVED + " < " + date + " END)");
|
|
|
|
|
|
|
|
Log.w("MmsDatabase", "Executing trim query: " + where);
|
|
|
|
cursor = db.query(TABLE_NAME, new String[] {ID}, where, new String[] {threadId+""}, null, null, null);
|
|
|
|
|
|
|
|
while (cursor != null && cursor.moveToNext()) {
|
|
|
|
Log.w("MmsDatabase", "Trimming: " + cursor.getLong(0));
|
|
|
|
delete(cursor.getLong(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
if (cursor != null)
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public void deleteAllThreads() {
|
|
|
|
DatabaseFactory.getPartDatabase(context).deleteAllParts();
|
|
|
|
DatabaseFactory.getMmsAddressDatabase(context).deleteAllAddresses();
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
|
|
|
database.delete(TABLE_NAME, null, null);
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2012-09-30 18:46:45 +00:00
|
|
|
public Cursor getCarrierMmsInformation(String apn) {
|
2012-11-21 03:09:46 +00:00
|
|
|
Uri uri = Uri.withAppendedPath(Uri.parse("content://telephony/carriers"), "current");
|
2013-02-27 06:55:23 +00:00
|
|
|
String selection = Util.isEmpty(apn) ? null : "apn = ?";
|
|
|
|
String[] selectionArgs = Util.isEmpty(apn) ? null : new String[] {apn.trim()};
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-03-17 18:19:36 +00:00
|
|
|
try {
|
|
|
|
return context.getContentResolver().query(uri, null, selection, selectionArgs, null);
|
|
|
|
} catch (NullPointerException npe) {
|
|
|
|
// NOTE - This is dumb, but on some devices there's an NPE in the Android framework
|
|
|
|
// for the provider of this call, which gets rethrown back to here through a binder
|
|
|
|
// call.
|
|
|
|
throw new IllegalArgumentException(npe);
|
|
|
|
}
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private PduHeaders getHeadersFromCursor(Cursor cursor) throws InvalidHeaderValueException {
|
|
|
|
PduHeaders headers = new PduHeaders();
|
|
|
|
PduHeadersBuilder phb = new PduHeadersBuilder(headers, cursor);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
phb.add(RETRIEVE_TEXT, RETRIEVE_TEXT_CS, PduHeaders.RETRIEVE_TEXT);
|
|
|
|
phb.add(SUBJECT, SUBJECT_CHARSET, PduHeaders.SUBJECT);
|
|
|
|
phb.addText(CONTENT_LOCATION, PduHeaders.CONTENT_LOCATION);
|
|
|
|
phb.addText(CONTENT_TYPE, PduHeaders.CONTENT_TYPE);
|
|
|
|
phb.addText(MESSAGE_CLASS, PduHeaders.MESSAGE_CLASS);
|
|
|
|
phb.addText(MESSAGE_ID, PduHeaders.MESSAGE_ID);
|
|
|
|
phb.addText(RESPONSE_TEXT, PduHeaders.RESPONSE_TEXT);
|
|
|
|
phb.addText(TRANSACTION_ID, PduHeaders.TRANSACTION_ID);
|
|
|
|
phb.addOctet(CONTENT_CLASS, PduHeaders.CONTENT_CLASS);
|
|
|
|
phb.addOctet(DELIVERY_REPORT, PduHeaders.DELIVERY_REPORT);
|
|
|
|
phb.addOctet(MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE);
|
|
|
|
phb.addOctet(MMS_VERSION, PduHeaders.MMS_VERSION);
|
|
|
|
phb.addOctet(PRIORITY, PduHeaders.PRIORITY);
|
|
|
|
phb.addOctet(READ_STATUS, PduHeaders.READ_STATUS);
|
|
|
|
phb.addOctet(REPORT_ALLOWED, PduHeaders.REPORT_ALLOWED);
|
|
|
|
phb.addOctet(RETRIEVE_STATUS, PduHeaders.RETRIEVE_STATUS);
|
|
|
|
phb.addOctet(STATUS, PduHeaders.STATUS);
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
phb.addLong(NORMALIZED_DATE_SENT, PduHeaders.DATE);
|
2011-12-20 18:20:44 +00:00
|
|
|
phb.addLong(DELIVERY_TIME, PduHeaders.DELIVERY_TIME);
|
|
|
|
phb.addLong(EXPIRY, PduHeaders.EXPIRY);
|
|
|
|
phb.addLong(MESSAGE_SIZE, PduHeaders.MESSAGE_SIZE);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
headers.setLongInteger(headers.getLongInteger(PduHeaders.DATE) / 1000L, PduHeaders.DATE);
|
|
|
|
|
|
|
|
return headers;
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
private ContentValues getContentValuesFromHeader(PduHeaders headers) {
|
|
|
|
ContentValues contentValues = new ContentValues();
|
|
|
|
ContentValuesBuilder cvb = new ContentValuesBuilder(contentValues);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
cvb.add(RETRIEVE_TEXT, RETRIEVE_TEXT_CS, headers.getEncodedStringValue(PduHeaders.RETRIEVE_TEXT));
|
|
|
|
cvb.add(SUBJECT, SUBJECT_CHARSET, headers.getEncodedStringValue(PduHeaders.SUBJECT));
|
|
|
|
cvb.add(CONTENT_LOCATION, headers.getTextString(PduHeaders.CONTENT_LOCATION));
|
|
|
|
cvb.add(CONTENT_TYPE, headers.getTextString(PduHeaders.CONTENT_TYPE));
|
|
|
|
cvb.add(MESSAGE_CLASS, headers.getTextString(PduHeaders.MESSAGE_CLASS));
|
|
|
|
cvb.add(MESSAGE_ID, headers.getTextString(PduHeaders.MESSAGE_ID));
|
|
|
|
cvb.add(RESPONSE_TEXT, headers.getTextString(PduHeaders.RESPONSE_TEXT));
|
|
|
|
cvb.add(TRANSACTION_ID, headers.getTextString(PduHeaders.TRANSACTION_ID));
|
|
|
|
cvb.add(CONTENT_CLASS, headers.getOctet(PduHeaders.CONTENT_CLASS));
|
|
|
|
cvb.add(DELIVERY_REPORT, headers.getOctet(PduHeaders.DELIVERY_REPORT));
|
|
|
|
cvb.add(MESSAGE_TYPE, headers.getOctet(PduHeaders.MESSAGE_TYPE));
|
|
|
|
cvb.add(MMS_VERSION, headers.getOctet(PduHeaders.MMS_VERSION));
|
|
|
|
cvb.add(PRIORITY, headers.getOctet(PduHeaders.PRIORITY));
|
|
|
|
cvb.add(READ_REPORT, headers.getOctet(PduHeaders.READ_REPORT));
|
|
|
|
cvb.add(READ_STATUS, headers.getOctet(PduHeaders.READ_STATUS));
|
|
|
|
cvb.add(REPORT_ALLOWED, headers.getOctet(PduHeaders.REPORT_ALLOWED));
|
|
|
|
cvb.add(RETRIEVE_STATUS, headers.getOctet(PduHeaders.RETRIEVE_STATUS));
|
|
|
|
cvb.add(STATUS, headers.getOctet(PduHeaders.STATUS));
|
2013-01-06 21:13:14 +00:00
|
|
|
cvb.add(DATE_SENT, headers.getLongInteger(PduHeaders.DATE));
|
2011-12-20 18:20:44 +00:00
|
|
|
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));
|
2013-05-31 03:29:13 +00:00
|
|
|
|
|
|
|
if (headers.getEncodedStringValue(PduHeaders.FROM) != null)
|
|
|
|
cvb.add(ADDRESS, headers.getEncodedStringValue(PduHeaders.FROM).getTextString());
|
|
|
|
else
|
|
|
|
cvb.add(ADDRESS, null);
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
return cvb.getContentValues();
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
protected PartDatabase getPartDatabase(MasterSecret masterSecret) {
|
|
|
|
if (masterSecret == null)
|
|
|
|
return DatabaseFactory.getPartDatabase(context);
|
|
|
|
else
|
|
|
|
return DatabaseFactory.getEncryptingPartDatabase(context, masterSecret);
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public Reader readerFor(MasterSecret masterSecret, Cursor cursor) {
|
|
|
|
return new Reader(masterSecret, cursor);
|
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public static class Status {
|
2011-12-20 18:20:44 +00:00
|
|
|
public static final int DOWNLOAD_INITIALIZED = 1;
|
|
|
|
public static final int DOWNLOAD_NO_CONNECTIVITY = 2;
|
|
|
|
public static final int DOWNLOAD_CONNECTING = 3;
|
2012-10-01 02:56:29 +00:00
|
|
|
public static final int DOWNLOAD_SOFT_FAILURE = 4;
|
|
|
|
public static final int DOWNLOAD_HARD_FAILURE = 5;
|
2011-12-20 18:20:44 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public static boolean isDisplayDownloadButton(int status) {
|
|
|
|
return
|
|
|
|
status == DOWNLOAD_INITIALIZED ||
|
|
|
|
status == DOWNLOAD_NO_CONNECTIVITY ||
|
|
|
|
status == DOWNLOAD_SOFT_FAILURE;
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public static String getLabelForStatus(Context context, int status) {
|
|
|
|
switch (status) {
|
|
|
|
case DOWNLOAD_CONNECTING: return context.getString(R.string.MmsDatabase_connecting_to_mms_server);
|
|
|
|
case DOWNLOAD_INITIALIZED: return context.getString(R.string.MmsDatabase_downloading_mms);
|
|
|
|
case DOWNLOAD_HARD_FAILURE: return context.getString(R.string.MmsDatabase_mms_download_failed);
|
2013-01-10 05:06:56 +00:00
|
|
|
}
|
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
return context.getString(R.string.MmsDatabase_downloading);
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public static boolean isHardError(int status) {
|
|
|
|
return status == DOWNLOAD_HARD_FAILURE;
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public class Reader {
|
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
private final Cursor cursor;
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
private final MasterSecret masterSecret;
|
2013-04-26 18:23:43 +00:00
|
|
|
private final MasterCipher masterCipher;
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
|
|
|
|
public Reader(MasterSecret masterSecret, Cursor cursor) {
|
|
|
|
this.cursor = cursor;
|
|
|
|
this.masterSecret = masterSecret;
|
2013-04-26 18:23:43 +00:00
|
|
|
|
|
|
|
if (masterSecret != null) masterCipher = new MasterCipher(masterSecret);
|
|
|
|
else masterCipher = null;
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public MessageRecord getNext() {
|
|
|
|
if (cursor == null || !cursor.moveToNext())
|
|
|
|
return null;
|
|
|
|
|
|
|
|
return getCurrent();
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public MessageRecord getCurrent() {
|
|
|
|
long mmsType = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_TYPE));
|
2012-09-08 03:03:23 +00:00
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
if (mmsType == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND) {
|
|
|
|
return getNotificationMmsMessageRecord(cursor);
|
|
|
|
} else {
|
|
|
|
return getMediaMmsMessageRecord(cursor);
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
}
|
2012-09-08 03:03:23 +00:00
|
|
|
|
2013-05-05 19:51:36 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
private MediaMmsMessageRecord getMediaMmsMessageRecord(Cursor cursor) {
|
2013-04-30 18:14:01 +00:00
|
|
|
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));
|
2013-05-05 19:51:36 +00:00
|
|
|
String address = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS));
|
2013-04-30 18:14:01 +00:00
|
|
|
DisplayRecord.Body body = getBody(cursor);
|
|
|
|
int partCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.PART_COUNT));
|
2013-05-05 19:51:36 +00:00
|
|
|
Recipients recipients = getRecipientsFor(address);
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
ListenableFutureTask<SlideDeck> slideDeck = getSlideDeck(masterSecret, id);
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
|
2013-05-05 19:51:36 +00:00
|
|
|
return new MediaMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
|
2013-04-26 18:23:43 +00:00
|
|
|
dateSent, dateReceived, threadId, body,
|
|
|
|
slideDeck, partCount, box);
|
|
|
|
}
|
|
|
|
|
2013-05-05 19:51:36 +00:00
|
|
|
private Recipients getRecipientsFor(String address) {
|
|
|
|
try {
|
2013-05-06 19:33:42 +00:00
|
|
|
if (Util.isEmpty(address) || address.equals("insert-address-token")) {
|
2013-05-05 19:51:36 +00:00
|
|
|
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)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-30 18:14:01 +00:00
|
|
|
private DisplayRecord.Body getBody(Cursor cursor) {
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
try {
|
2013-04-26 18:23:43 +00:00
|
|
|
String body = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.BODY));
|
|
|
|
long box = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
|
2013-04-30 18:14:01 +00:00
|
|
|
if (!Util.isEmpty(body) && masterCipher != null && Types.isSymmetricEncryption(box)) {
|
|
|
|
return new DisplayRecord.Body(masterCipher.decryptBody(body), true);
|
|
|
|
} else if (!Util.isEmpty(body) && masterCipher == null && Types.isSymmetricEncryption(box)) {
|
|
|
|
return new DisplayRecord.Body(body, false);
|
|
|
|
} else {
|
|
|
|
return new DisplayRecord.Body(body == null ? "" : body, true);
|
2013-04-26 18:23:43 +00:00
|
|
|
}
|
|
|
|
} catch (InvalidMessageException e) {
|
|
|
|
Log.w("MmsDatabase", e);
|
2013-04-30 18:14:01 +00:00
|
|
|
return new DisplayRecord.Body("Error decrypting message.", true);
|
2013-04-26 18:23:43 +00:00
|
|
|
}
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
private ListenableFutureTask<SlideDeck> getSlideDeck(final MasterSecret masterSecret,
|
|
|
|
final long id)
|
|
|
|
{
|
2013-05-06 19:22:03 +00:00
|
|
|
ListenableFutureTask<SlideDeck> future = getCachedSlideDeck(id);
|
|
|
|
|
|
|
|
if (future != null) {
|
|
|
|
return future;
|
|
|
|
}
|
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
Callable<SlideDeck> task = new Callable<SlideDeck>() {
|
|
|
|
@Override
|
|
|
|
public SlideDeck call() throws Exception {
|
2013-05-05 19:51:36 +00:00
|
|
|
if (masterSecret == null)
|
2013-04-26 18:23:43 +00:00
|
|
|
return null;
|
2013-05-05 19:51:36 +00:00
|
|
|
|
|
|
|
PduBody body = getPartDatabase(masterSecret).getParts(id, false);
|
2013-05-06 19:22:03 +00:00
|
|
|
SlideDeck slideDeck = new SlideDeck(context, masterSecret, body);
|
|
|
|
slideCache.put(id, new SoftReference<SlideDeck>(slideDeck));
|
|
|
|
|
|
|
|
return slideDeck;
|
2013-04-26 18:23:43 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-05-06 19:22:03 +00:00
|
|
|
future = new ListenableFutureTask<SlideDeck>(task, null);
|
2013-04-26 18:23:43 +00:00
|
|
|
slideResolver.execute(future);
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
|
2013-04-26 18:23:43 +00:00
|
|
|
return future;
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
}
|
|
|
|
|
2013-05-06 19:22:03 +00:00
|
|
|
private ListenableFutureTask<SlideDeck> getCachedSlideDeck(final long id) {
|
|
|
|
SoftReference<SlideDeck> reference = slideCache.get(id);
|
|
|
|
|
|
|
|
if (reference != null) {
|
|
|
|
final SlideDeck slideDeck = reference.get();
|
|
|
|
|
|
|
|
if (slideDeck != null) {
|
|
|
|
Callable<SlideDeck> task = new Callable<SlideDeck>() {
|
|
|
|
@Override
|
|
|
|
public SlideDeck call() throws Exception {
|
|
|
|
return slideDeck;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
ListenableFutureTask<SlideDeck> future = new ListenableFutureTask<SlideDeck>(task, null);
|
|
|
|
future.run();
|
|
|
|
|
|
|
|
return future;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
public void close() {
|
|
|
|
cursor.close();
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|
|
|
|
}
|
Major storage layer refactoring to set the stage for clean GCM.
1) We now try to hand out cursors at a minimum. There has always been
a fairly clean insertion layer that handles encrypting message bodies,
but the process of decrypting message bodies has always been less than
ideal. Here we introduce a "Reader" interface that will decrypt message
bodies when appropriate and return objects that encapsulate record state.
No more MessageDisplayHelper. The MmsSmsDatabase interface is also more
sane.
2) We finally rid ourselves of the technical debt associated with TextSecure's
initial usage of the default SMS DB. In that world, we weren't able to use
anything other than the default "Inbox, Outbox, Sent" types to describe a
message, and had to overload the message content itself with a set of
local "prefixes" to describe what it was (encrypted, asymetric encrypted,
remote encrypted, a key exchange, procssed key exchange), and so on.
This includes a major schema update that transforms the "type" field into
a bitmask that describes everything that used to be encoded in a prefix,
and prefixes have been completely eliminated from the system.
No more Prefix.java
3) Refactoring of the MultipartMessageHandler code. It's less of a mess, and
hopefully more clear as to what's going on.
The next step is to remove what we can from SmsTransportDetails and genericize
that interface for a GCM equivalent.
2013-04-20 19:22:04 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|