diff --git a/build.gradle b/build.gradle
index 1ee0f3fd4b..38e7a2c88f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -203,7 +203,7 @@ android {
}
defaultConfig {
- versionCode 275
+ versionCode 276
versionName "4.8.1"
minSdkVersion 9
diff --git a/src/org/thoughtcrime/securesms/BlockedContactsActivity.java b/src/org/thoughtcrime/securesms/BlockedContactsActivity.java
index e9f4f491bc..c391c879c8 100644
--- a/src/org/thoughtcrime/securesms/BlockedContactsActivity.java
+++ b/src/org/thoughtcrime/securesms/BlockedContactsActivity.java
@@ -17,6 +17,7 @@ import android.widget.AdapterView;
import android.widget.ListView;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.loaders.BlockedContactsLoader;
import org.thoughtcrime.securesms.preferences.BlockedContactListItem;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
@@ -24,6 +25,8 @@ import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
+import java.util.List;
+
public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity {
private final DynamicTheme dynamicTheme = new DynamicTheme();
@@ -105,7 +108,7 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
public void onItemClick(AdapterView> parent, View view, int position, long id) {
Recipients recipients = ((BlockedContactListItem)view).getRecipients();
Intent intent = new Intent(getActivity(), RecipientPreferenceActivity.class);
- intent.putExtra(RecipientPreferenceActivity.RECIPIENTS_EXTRA, recipients.getIds());
+ intent.putExtra(RecipientPreferenceActivity.ADDRESSES_EXTRA, recipients.getAddresses());
startActivity(intent);
}
@@ -124,8 +127,10 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
@Override
public void bindView(View view, Context context, Cursor cursor) {
- String recipientIds = cursor.getString(1);
- Recipients recipients = RecipientFactory.getRecipientsForIds(context, recipientIds, true);
+ String addressesConcat = cursor.getString(1);
+ List
addresses = Address.fromSerializedList(addressesConcat, " ");
+
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, addresses.toArray(new Address[0]), true);
((BlockedContactListItem) view).set(recipients);
}
diff --git a/src/org/thoughtcrime/securesms/ConfirmIdentityDialog.java b/src/org/thoughtcrime/securesms/ConfirmIdentityDialog.java
index a926447723..c33a6c4ff5 100644
--- a/src/org/thoughtcrime/securesms/ConfirmIdentityDialog.java
+++ b/src/org/thoughtcrime/securesms/ConfirmIdentityDialog.java
@@ -8,12 +8,11 @@ import android.support.v7.app.AlertDialog;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
-import android.util.Log;
import android.widget.TextView;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
-import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsAddressDatabase;
import org.thoughtcrime.securesms.database.MmsDatabase;
@@ -28,12 +27,9 @@ import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.Base64;
-import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.VerifySpan;
import org.whispersystems.libsignal.SignalProtocolAddress;
-import org.whispersystems.libsignal.state.IdentityKeyStore;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
import java.io.IOException;
@@ -53,10 +49,8 @@ public class ConfirmIdentityDialog extends AlertDialog {
{
super(context);
- try {
- Recipient recipient = RecipientFactory.getRecipientForId(context, mismatch.getRecipientId(), false);
+ Recipient recipient = RecipientFactory.getRecipientFor(context, mismatch.getAddress(), false);
String name = recipient.toShortString();
- String number = Util.canonicalizeNumber(context, recipient.getNumber());
String introduction = String.format(context.getString(R.string.ConfirmIdentityDialog_your_safety_number_with_s_has_changed), name, name);
SpannableString spannableString = new SpannableString(introduction + " " +
context.getString(R.string.ConfirmIdentityDialog_you_may_wish_to_verify_your_safety_number_with_this_contact));
@@ -68,11 +62,8 @@ public class ConfirmIdentityDialog extends AlertDialog {
setTitle(name);
setMessage(spannableString);
- setButton(AlertDialog.BUTTON_POSITIVE, context.getString(R.string.ConfirmIdentityDialog_accept), new AcceptListener(masterSecret, messageRecord, mismatch, number));
+ setButton(AlertDialog.BUTTON_POSITIVE, context.getString(R.string.ConfirmIdentityDialog_accept), new AcceptListener(masterSecret, messageRecord, mismatch, recipient.getAddress()));
setButton(AlertDialog.BUTTON_NEGATIVE, context.getString(android.R.string.cancel), new CancelListener());
- } catch (InvalidNumberException e) {
- throw new AssertionError(e);
- }
}
@Override
@@ -91,13 +82,13 @@ public class ConfirmIdentityDialog extends AlertDialog {
private final MasterSecret masterSecret;
private final MessageRecord messageRecord;
private final IdentityKeyMismatch mismatch;
- private final String number;
+ private final Address address;
- private AcceptListener(MasterSecret masterSecret, MessageRecord messageRecord, IdentityKeyMismatch mismatch, String number) {
+ private AcceptListener(MasterSecret masterSecret, MessageRecord messageRecord, IdentityKeyMismatch mismatch, Address address) {
this.masterSecret = masterSecret;
this.messageRecord = messageRecord;
this.mismatch = mismatch;
- this.number = number;
+ this.address = address;
}
@Override
@@ -107,7 +98,7 @@ public class ConfirmIdentityDialog extends AlertDialog {
@Override
protected Void doInBackground(Void... params) {
synchronized (SESSION_LOCK) {
- SignalProtocolAddress mismatchAddress = new SignalProtocolAddress(number, 1);
+ SignalProtocolAddress mismatchAddress = new SignalProtocolAddress(address.toPhoneString(), 1);
TextSecureIdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(getContext());
identityKeyStore.saveIdentity(mismatchAddress, mismatch.getIdentityKey(), true);
@@ -151,16 +142,16 @@ public class ConfirmIdentityDialog extends AlertDialog {
if (messageRecord.isMms()) {
mmsDatabase.removeMismatchedIdentity(messageRecord.getId(),
- mismatch.getRecipientId(),
+ mismatch.getAddress(),
mismatch.getIdentityKey());
Recipients recipients = mmsAddressDatabase.getRecipientsForId(messageRecord.getId());
- if (recipients.isGroupRecipient()) MessageSender.resendGroupMessage(getContext(), masterSecret, messageRecord, mismatch.getRecipientId());
+ if (recipients.isGroupRecipient()) MessageSender.resendGroupMessage(getContext(), masterSecret, messageRecord, mismatch.getAddress());
else MessageSender.resend(getContext(), masterSecret, messageRecord);
} else {
smsDatabase.removeMismatchedIdentity(messageRecord.getId(),
- mismatch.getRecipientId(),
+ mismatch.getAddress(),
mismatch.getIdentityKey());
MessageSender.resend(getContext(), masterSecret, messageRecord);
@@ -173,13 +164,13 @@ public class ConfirmIdentityDialog extends AlertDialog {
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(getContext());
smsDatabase.removeMismatchedIdentity(messageRecord.getId(),
- mismatch.getRecipientId(),
+ mismatch.getAddress(),
mismatch.getIdentityKey());
boolean legacy = !messageRecord.isContentBundleKeyExchange();
SignalServiceEnvelope envelope = new SignalServiceEnvelope(SignalServiceProtos.Envelope.Type.PREKEY_BUNDLE_VALUE,
- messageRecord.getIndividualRecipient().getNumber(),
+ messageRecord.getIndividualRecipient().getAddress().toPhoneString(),
messageRecord.getRecipientDeviceId(), "",
messageRecord.getDateSent(),
legacy ? Base64.decode(messageRecord.getBody().getBody()) : null,
@@ -189,8 +180,7 @@ public class ConfirmIdentityDialog extends AlertDialog {
ApplicationContext.getInstance(getContext())
.getJobManager()
- .add(new PushDecryptJob(getContext(), pushId, messageRecord.getId(),
- messageRecord.getIndividualRecipient().getNumber()));
+ .add(new PushDecryptJob(getContext(), pushId, messageRecord.getId()));
} catch (IOException e) {
throw new AssertionError(e);
}
diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java
index 065f03af6e..68ea836ee2 100644
--- a/src/org/thoughtcrime/securesms/ConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/ConversationActivity.java
@@ -97,6 +97,7 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.crypto.MasterCipher;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.SecurityEvent;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.DraftDatabase;
import org.thoughtcrime.securesms.database.DraftDatabase.Draft;
@@ -164,7 +165,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
-import java.util.LinkedList;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
@@ -191,7 +192,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
{
private static final String TAG = ConversationActivity.class.getSimpleName();
- public static final String RECIPIENTS_EXTRA = "recipients";
+ public static final String ADDRESSES_EXTRA = "addresses";
public static final String THREAD_ID_EXTRA = "thread_id";
public static final String IS_ARCHIVED_EXTRA = "is_archived";
public static final String TEXT_EXTRA = "draft_text";
@@ -409,7 +410,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
addAttachmentContactInfo(data.getData());
break;
case GROUP_EDIT:
- recipients = RecipientFactory.getRecipientsForIds(this, data.getLongArrayExtra(GroupCreateActivity.GROUP_RECIPIENT_EXTRA), true);
+ recipients = RecipientFactory.getRecipientsFor(this, RecipientFactory.getRecipientFor(this, (Address)data.getParcelableExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA), true), true);
recipients.addListener(this);
titleView.setTitle(recipients);
setBlockedUserState(recipients, isSecureText, isDefaultSms);
@@ -421,7 +422,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
break;
case ADD_CONTACT:
- recipients = RecipientFactory.getRecipientsForIds(ConversationActivity.this, recipients.getIds(), true);
+ recipients = RecipientFactory.getRecipientsFor(this, recipients.getAddresses(), true);
recipients.addListener(this);
fragment.reloadList();
break;
@@ -679,7 +680,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
composeText.appendInvite(inviteText);
} else {
Intent intent = new Intent(Intent.ACTION_SENDTO);
- intent.setData(Uri.parse("smsto:" + recipients.getPrimaryRecipient().getNumber()));
+ intent.setData(Uri.parse("smsto:" + recipients.getPrimaryRecipient().getAddress().serialize()));
intent.putExtra("sms_body", inviteText);
intent.putExtra(Intent.EXTRA_TEXT, inviteText);
startActivity(intent);
@@ -725,7 +726,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void handleViewMedia() {
Intent intent = new Intent(this, MediaOverviewActivity.class);
intent.putExtra(MediaOverviewActivity.THREAD_ID_EXTRA, threadId);
- intent.putExtra(MediaOverviewActivity.RECIPIENT_EXTRA, recipients.getPrimaryRecipient().getRecipientId());
+ intent.putExtra(MediaOverviewActivity.ADDRESSES_EXTRA, recipients.getAddresses());
startActivity(intent);
}
@@ -746,7 +747,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public void onClick(DialogInterface dialog, int which) {
Context self = ConversationActivity.this;
try {
- byte[] groupId = GroupUtil.getDecodedId(getRecipients().getPrimaryRecipient().getNumber());
+ byte[] groupId = GroupUtil.getDecodedId(getRecipients().getPrimaryRecipient().getAddress().toGroupString());
DatabaseFactory.getGroupDatabase(self).setActive(groupId, false);
GroupContext context = GroupContext.newBuilder()
@@ -756,7 +757,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(getRecipients(), context, null, System.currentTimeMillis(), 0);
MessageSender.send(self, masterSecret, outgoingMessage, threadId, false, null);
- DatabaseFactory.getGroupDatabase(self).remove(groupId, TextSecurePreferences.getLocalNumber(self));
+ DatabaseFactory.getGroupDatabase(self).remove(groupId, Address.fromSerialized(TextSecurePreferences.getLocalNumber(self)));
initializeEnabledCheck();
} catch (IOException e) {
Log.w(TAG, e);
@@ -771,7 +772,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void handleEditPushGroup() {
Intent intent = new Intent(ConversationActivity.this, GroupCreateActivity.class);
- intent.putExtra(GroupCreateActivity.GROUP_RECIPIENT_EXTRA, recipients.getPrimaryRecipient().getRecipientId());
+ intent.putExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA, recipients.getPrimaryRecipient().getAddress());
startActivityForResult(intent, GROUP_EDIT);
}
@@ -813,7 +814,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if (isSecureText) {
Intent intent = new Intent(this, WebRtcCallService.class);
intent.setAction(WebRtcCallService.ACTION_OUTGOING_CALL);
- intent.putExtra(WebRtcCallService.EXTRA_REMOTE_NUMBER, recipient.getNumber());
+ intent.putExtra(WebRtcCallService.EXTRA_REMOTE_ADDRESS, recipient.getAddress());
startService(intent);
Intent activityIntent = new Intent(this, WebRtcCallActivity.class);
@@ -822,7 +823,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} else {
try {
Intent dialIntent = new Intent(Intent.ACTION_DIAL,
- Uri.parse("tel:" + recipient.getNumber()));
+ Uri.parse("tel:" + recipient.getAddress().serialize()));
startActivity(dialIntent);
} catch (ActivityNotFoundException anfe) {
Log.w(TAG, anfe);
@@ -838,9 +839,15 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void handleAddToContacts() {
+ if (recipients.getPrimaryRecipient().getAddress().isGroup()) return;
+
try {
final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
- intent.putExtra(ContactsContract.Intents.Insert.PHONE, recipients.getPrimaryRecipient().getNumber());
+ if (recipients.getPrimaryRecipient().getAddress().isEmail()) {
+ intent.putExtra(ContactsContract.Intents.Insert.EMAIL, recipients.getPrimaryRecipient().getAddress().toEmailString());
+ } else {
+ intent.putExtra(ContactsContract.Intents.Insert.PHONE, recipients.getPrimaryRecipient().getAddress().toPhoneString());
+ }
intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
startActivityForResult(intent, ADD_CONTACT);
} catch (ActivityNotFoundException e) {
@@ -1103,12 +1110,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if (recipients.isGroupRecipient()) {
recipients = DatabaseFactory.getGroupDatabase(ConversationActivity.this)
- .getGroupMembers(GroupUtil.getDecodedId(recipients.getPrimaryRecipient().getNumber()), false);
+ .getGroupMembers(GroupUtil.getDecodedId(recipients.getPrimaryRecipient().getAddress().toGroupString()), false);
}
- for (long recipientId : recipients.getIds()) {
- Log.w(TAG, "Loading identity for: " + recipientId);
- identityRecordList.add(identityDatabase.getIdentity(recipientId));
+ for (Address recipientAddress : recipients.getAddresses()) {
+ Log.w(TAG, "Loading identity for: " + recipientAddress);
+ identityRecordList.add(identityDatabase.getIdentity(recipientAddress));
}
String message = null;
@@ -1206,7 +1213,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void onClick(View v) {
Intent intent = new Intent(ConversationActivity.this, RecipientPreferenceActivity.class);
- intent.putExtra(RecipientPreferenceActivity.RECIPIENTS_EXTRA, recipients.getIds());
+ intent.putExtra(RecipientPreferenceActivity.ADDRESSES_EXTRA, recipients.getAddresses());
intent.putExtra(RecipientPreferenceActivity.CAN_HAVE_SAFETY_NUMBER_EXTRA,
isSecureText && !isSelfConversation());
@@ -1253,7 +1260,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void initializeResources() {
if (recipients != null) recipients.removeListener(this);
- recipients = RecipientFactory.getRecipientsForIds(this, getIntent().getLongArrayExtra(RECIPIENTS_EXTRA), true);
+ recipients = RecipientFactory.getRecipientsFor(this, Address.fromParcelable(getIntent().getParcelableArrayExtra(ADDRESSES_EXTRA)), true);
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
archived = getIntent().getBooleanExtra(IS_ARCHIVED_EXTRA, false);
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
@@ -1295,7 +1302,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Subscribe(threadMode = ThreadMode.MAIN)
public void onRecipientPreferenceUpdate(final RecipientPreferenceEvent event) {
- if (event.getRecipients().getSortedIdsString().equals(this.recipients.getSortedIdsString())) {
+ if (Arrays.equals(event.getRecipients().getAddresses(), this.recipients.getAddresses())) {
new RecipientPreferencesTask().execute(this.recipients);
}
}
@@ -1319,9 +1326,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public void onReceive(Context context, Intent intent) {
Log.w(TAG, "Group update received...");
if (recipients != null) {
- long[] ids = recipients.getIds();
Log.w(TAG, "Looking up new recipients...");
- recipients = RecipientFactory.getRecipientsForIds(context, ids, true);
+ recipients = RecipientFactory.getRecipientsFor(context, recipients.getAddresses(), true);
recipients.addListener(ConversationActivity.this);
onModified(recipients);
fragment.reloadList();
@@ -1501,7 +1507,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if (!isGroupConversation()) return false;
try {
- byte[] groupId = GroupUtil.getDecodedId(getRecipients().getPrimaryRecipient().getNumber());
+ byte[] groupId = GroupUtil.getDecodedId(getRecipients().getPrimaryRecipient().getAddress().toGroupString());
GroupRecord record = DatabaseFactory.getGroupDatabase(this).getGroup(groupId);
return record != null && record.isActive();
@@ -1516,7 +1522,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if (!recipients.isSingleRecipient()) return false;
if (recipients.getPrimaryRecipient().isGroupRecipient()) return false;
- return Util.isOwnNumber(this, recipients.getPrimaryRecipient().getNumber());
+ return Util.isOwnNumber(this, recipients.getPrimaryRecipient().getAddress());
}
private boolean isGroupConversation() {
@@ -2000,7 +2006,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
Optional prefs = DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
- .getRecipientsPreferences(recipients[0].getIds());
+ .getRecipientsPreferences(recipients[0].getAddresses());
return new Pair<>(recipients[0], prefs.orNull());
}
@@ -2023,7 +2029,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
protected Void doInBackground(Void... params) {
synchronized (SESSION_LOCK) {
for (IdentityRecord identityRecord : unverifiedIdentities) {
- identityDatabase.setVerified(identityRecord.getRecipientId(),
+ identityDatabase.setVerified(identityRecord.getAddress(),
identityRecord.getIdentityKey(),
VerifiedStatus.DEFAULT);
}
@@ -2046,7 +2052,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
Log.w(TAG, "onClicked: " + unverifiedIdentities.size());
if (unverifiedIdentities.size() == 1) {
Intent intent = new Intent(ConversationActivity.this, VerifyIdentityActivity.class);
- intent.putExtra(VerifyIdentityActivity.RECIPIENT_ID_EXTRA, unverifiedIdentities.get(0).getRecipientId());
+ intent.putExtra(VerifyIdentityActivity.ADDRESS_EXTRA, unverifiedIdentities.get(0).getAddress());
intent.putExtra(VerifyIdentityActivity.IDENTITY_EXTRA, new IdentityKeyParcelable(unverifiedIdentities.get(0).getIdentityKey()));
intent.putExtra(VerifyIdentityActivity.VERIFIED_EXTRA, false);
@@ -2055,7 +2061,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
String[] unverifiedNames = new String[unverifiedIdentities.size()];
for (int i=0;i= VERSION_CODES.JELLY_BEAN) {
diff --git a/src/org/thoughtcrime/securesms/ConversationTitleView.java b/src/org/thoughtcrime/securesms/ConversationTitleView.java
index 93676a00bd..86a35278ba 100644
--- a/src/org/thoughtcrime/securesms/ConversationTitleView.java
+++ b/src/org/thoughtcrime/securesms/ConversationTitleView.java
@@ -69,14 +69,14 @@ public class ConversationTitleView extends LinearLayout {
private void setRecipientTitle(Recipient recipient) {
if (!recipient.isGroupRecipient()) {
if (TextUtils.isEmpty(recipient.getName())) {
- this.title.setText(recipient.getNumber());
+ this.title.setText(recipient.getAddress().serialize());
this.subtitle.setText(null);
this.subtitle.setVisibility(View.GONE);
} else {
this.title.setText(recipient.getName());
if (recipient.getCustomLabel() != null) this.subtitle.setText(recipient.getCustomLabel());
- else this.subtitle.setText(recipient.getNumber());
+ else this.subtitle.setText(recipient.getAddress().serialize());
this.subtitle.setVisibility(View.VISIBLE);
}
diff --git a/src/org/thoughtcrime/securesms/ConversationUpdateItem.java b/src/org/thoughtcrime/securesms/ConversationUpdateItem.java
index cbf321f3cc..ab5e8a6a26 100644
--- a/src/org/thoughtcrime/securesms/ConversationUpdateItem.java
+++ b/src/org/thoughtcrime/securesms/ConversationUpdateItem.java
@@ -221,7 +221,7 @@ public class ConversationUpdateItem extends LinearLayout
public void onSuccess(Optional result) {
if (result.isPresent()) {
Intent intent = new Intent(getContext(), VerifyIdentityActivity.class);
- intent.putExtra(VerifyIdentityActivity.RECIPIENT_ID_EXTRA, sender.getRecipientId());
+ intent.putExtra(VerifyIdentityActivity.ADDRESS_EXTRA, sender.getAddress());
intent.putExtra(VerifyIdentityActivity.IDENTITY_EXTRA, new IdentityKeyParcelable(result.get().getIdentityKey()));
intent.putExtra(VerifyIdentityActivity.VERIFIED_EXTRA, result.get().getVerifiedStatus() == IdentityDatabase.VerifiedStatus.VERIFIED);
diff --git a/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java b/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java
index d3b21ffc80..e03dece50a 100644
--- a/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java
+++ b/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java
@@ -68,7 +68,7 @@ public class DatabaseUpgradeActivity extends BaseActivity {
public static final int CONTACTS_ACCOUNT_VERSION = 136;
public static final int MEDIA_DOWNLOAD_CONTROLS_VERSION = 151;
public static final int REDPHONE_SUPPORT_VERSION = 157;
-// public static final int FINGERPRINTS_NON_BLOCKING_VESRION = 212;
+ public static final int NO_MORE_CANONICAL_DB_VERSION = 276;
private static final SortedSet UPGRADE_VERSIONS = new TreeSet() {{
add(NO_MORE_KEY_EXCHANGE_PREFIX_VERSION);
@@ -82,7 +82,7 @@ public class DatabaseUpgradeActivity extends BaseActivity {
add(MIGRATE_SESSION_PLAINTEXT);
add(MEDIA_DOWNLOAD_CONTROLS_VERSION);
add(REDPHONE_SUPPORT_VERSION);
-// add(FINGERPRINTS_NON_BLOCKING_VESRION);
+ add(NO_MORE_CANONICAL_DB_VERSION);
}};
private MasterSecret masterSecret;
@@ -233,10 +233,6 @@ public class DatabaseUpgradeActivity extends BaseActivity {
.add(new DirectoryRefreshJob(getApplicationContext()));
}
-// if (params[0] < FINGERPRINTS_NON_BLOCKING_VESRION) {
-// TextSecurePreferences.setBlockingIdentityUpdates(getApplicationContext(), true);
-// }
-
return null;
}
@@ -274,8 +270,7 @@ public class DatabaseUpgradeActivity extends BaseActivity {
ApplicationContext.getInstance(getApplicationContext())
.getJobManager()
.add(new PushDecryptJob(getApplicationContext(),
- pushReader.getLong(pushReader.getColumnIndexOrThrow(PushDatabase.ID)),
- pushReader.getString(pushReader.getColumnIndexOrThrow(PushDatabase.SOURCE))));
+ pushReader.getLong(pushReader.getColumnIndexOrThrow(PushDatabase.ID))));
}
} finally {
if (pushReader != null)
diff --git a/src/org/thoughtcrime/securesms/GroupCreateActivity.java b/src/org/thoughtcrime/securesms/GroupCreateActivity.java
index ee4f07b823..82e29e0538 100644
--- a/src/org/thoughtcrime/securesms/GroupCreateActivity.java
+++ b/src/org/thoughtcrime/securesms/GroupCreateActivity.java
@@ -50,6 +50,7 @@ import org.thoughtcrime.securesms.contacts.RecipientsEditor;
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
@@ -66,12 +67,11 @@ import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.GroupUtil;
-import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
import org.thoughtcrime.securesms.util.SelectedRecipientsAdapter;
import org.thoughtcrime.securesms.util.SelectedRecipientsAdapter.OnRecipientDeletedListener;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
+import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.util.InvalidNumberException;
@@ -95,8 +95,8 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
private final static String TAG = GroupCreateActivity.class.getSimpleName();
- public static final String GROUP_RECIPIENT_EXTRA = "group_recipient";
- public static final String GROUP_THREAD_EXTRA = "group_thread";
+ public static final String GROUP_ADDRESS_EXTRA = "group_recipient";
+ public static final String GROUP_THREAD_EXTRA = "group_thread";
private final DynamicTheme dynamicTheme = new DynamicTheme();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@@ -174,9 +174,8 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
private static boolean isActiveInDirectory(Context context, Recipient recipient) {
try {
- return TextSecureDirectory.getInstance(context)
- .isSecureTextSupported(Util.canonicalizeNumber(context, recipient.getNumber()));
- } catch (NotInDirectoryException | InvalidNumberException e) {
+ return TextSecureDirectory.getInstance(context).isSecureTextSupported(recipient.getAddress());
+ } catch (NotInDirectoryException e) {
return false;
}
}
@@ -213,11 +212,13 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
}
private void initializeExistingGroup() {
- final String encodedGroupId = RecipientFactory.getRecipientForId(this, getIntent().getLongExtra(GROUP_RECIPIENT_EXTRA, -1), true)
- .getNumber();
+ final Address groupAddress = getIntent().getParcelableExtra(GROUP_ADDRESS_EXTRA);
+
byte[] groupId;
+
try {
- groupId = GroupUtil.getDecodedId(encodedGroupId);
+ if (groupAddress != null) groupId = GroupUtil.getDecodedId(groupAddress.toGroupString());
+ else groupId = null;
} catch (IOException ioe) {
Log.w(TAG, "Couldn't decode the encoded groupId passed in via intent", ioe);
groupId = null;
@@ -286,7 +287,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
Intent intent = new Intent(this, ConversationActivity.class);
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
- intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds());
+ intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
startActivity(intent);
finish();
}
@@ -310,9 +311,12 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
switch (reqCode) {
case PICK_CONTACT:
List selected = data.getStringArrayListExtra("contacts");
+
for (String contact : selected) {
- final Recipient recipient = RecipientFactory.getRecipientsFromString(this, contact, false).getPrimaryRecipient();
- if (recipient != null) addSelectedContacts(recipient);
+ Address address = Address.fromExternal(this, contact);
+ Recipient recipient = RecipientFactory.getRecipientFor(this, address, false);
+
+ addSelectedContacts(recipient);
}
break;
@@ -470,7 +474,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
if (!activity.isFinishing()) {
Intent intent = activity.getIntent();
intent.putExtra(GROUP_THREAD_EXTRA, result.get().getThreadId());
- intent.putExtra(GROUP_RECIPIENT_EXTRA, result.get().getGroupRecipient().getIds());
+ intent.putExtra(GROUP_ADDRESS_EXTRA, result.get().getGroupRecipient().getPrimaryRecipient().getAddress());
activity.setResult(RESULT_OK, intent);
activity.finish();
}
@@ -508,16 +512,12 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
final List results = new LinkedList<>();
for (Recipient recipient : recipients) {
- boolean isPush = isActiveInDirectory(activity, recipient);
- String recipientE164 = null;
- try {
- recipientE164 = Util.canonicalizeNumber(activity, recipient.getNumber());
- } catch (InvalidNumberException ine) { /* do nothing */ }
+ boolean isPush = isActiveInDirectory(activity, recipient);
if (failIfNotPush && !isPush) {
results.add(new Result(null, false, activity.getString(R.string.GroupCreateActivity_cannot_add_non_push_to_existing_group,
- recipient.getNumber())));
- } else if (TextUtils.equals(TextSecurePreferences.getLocalNumber(activity), recipientE164)) {
+ recipient.toShortString())));
+ } else if (TextUtils.equals(TextSecurePreferences.getLocalNumber(activity), recipient.getAddress().serialize())) {
results.add(new Result(null, false, activity.getString(R.string.GroupCreateActivity_youre_already_in_the_group)));
} else {
results.add(new Result(recipient, isPush, null));
diff --git a/src/org/thoughtcrime/securesms/GroupMembersDialog.java b/src/org/thoughtcrime/securesms/GroupMembersDialog.java
index be6859d617..8c90e3981a 100644
--- a/src/org/thoughtcrime/securesms/GroupMembersDialog.java
+++ b/src/org/thoughtcrime/securesms/GroupMembersDialog.java
@@ -14,9 +14,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.GroupUtil;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.io.IOException;
import java.util.LinkedList;
@@ -40,7 +38,7 @@ public class GroupMembersDialog extends AsyncTask {
@Override
protected Recipients doInBackground(Void... params) {
try {
- String groupId = recipients.getPrimaryRecipient().getNumber();
+ String groupId = recipients.getPrimaryRecipient().getAddress().toGroupString();
return DatabaseFactory.getGroupDatabase(context)
.getGroupMembers(GroupUtil.getDecodedId(groupId), true);
} catch (IOException e) {
@@ -85,7 +83,11 @@ public class GroupMembersDialog extends AsyncTask {
ContactsContract.QuickContact.MODE_LARGE, null);
} else {
final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
- intent.putExtra(ContactsContract.Intents.Insert.PHONE, recipient.getNumber());
+ if (recipient.getAddress().isEmail()) {
+ intent.putExtra(ContactsContract.Intents.Insert.EMAIL, recipient.getAddress().toEmailString());
+ } else {
+ intent.putExtra(ContactsContract.Intents.Insert.PHONE, recipient.getAddress().toPhoneString());
+ }
intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
context.startActivity(intent);
}
@@ -134,15 +136,7 @@ public class GroupMembersDialog extends AsyncTask {
}
private boolean isLocalNumber(Recipient recipient) {
- try {
- String localNumber = TextSecurePreferences.getLocalNumber(context);
- String e164Number = Util.canonicalizeNumber(context, recipient.getNumber());
-
- return e164Number != null && e164Number.equals(localNumber);
- } catch (InvalidNumberException e) {
- Log.w(TAG, e);
- return false;
- }
+ return Util.isOwnNumber(context, recipient.getAddress());
}
}
}
diff --git a/src/org/thoughtcrime/securesms/InviteActivity.java b/src/org/thoughtcrime/securesms/InviteActivity.java
index c54badf51f..d0b4beded5 100644
--- a/src/org/thoughtcrime/securesms/InviteActivity.java
+++ b/src/org/thoughtcrime/securesms/InviteActivity.java
@@ -27,6 +27,7 @@ import android.widget.Toast;
import org.thoughtcrime.securesms.components.ContactFilterToolbar;
import org.thoughtcrime.securesms.components.ContactFilterToolbar.OnFilterChangedListener;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
@@ -230,10 +231,10 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
if (context == null) return null;
for (String number : numbers) {
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, number, false);
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, number)}, false);
if (recipients.getPrimaryRecipient() != null) {
- Optional preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(recipients.getIds());
+ Optional preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(recipients.getAddresses());
int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
MessageSender.send(context, masterSecret, new OutgoingTextMessage(recipients, message, subscriptionId), -1L, true, null);
diff --git a/src/org/thoughtcrime/securesms/MediaAdapter.java b/src/org/thoughtcrime/securesms/MediaAdapter.java
index 83769b1319..b18d561619 100644
--- a/src/org/thoughtcrime/securesms/MediaAdapter.java
+++ b/src/org/thoughtcrime/securesms/MediaAdapter.java
@@ -21,7 +21,6 @@ import android.content.Intent;
import android.database.Cursor;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
-import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -33,8 +32,6 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord;
import org.thoughtcrime.securesms.mms.Slide;
-import org.thoughtcrime.securesms.recipients.RecipientFactory;
-import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.MediaUtil;
public class MediaAdapter extends CursorRecyclerViewAdapter {
@@ -93,14 +90,10 @@ public class MediaAdapter extends CursorRecyclerViewAdapter {
intent.putExtra(MediaPreviewActivity.SIZE_EXTRA, mediaRecord.getAttachment().getSize());
intent.putExtra(MediaPreviewActivity.THREAD_ID_EXTRA, threadId);
- if (!TextUtils.isEmpty(mediaRecord.getAddress())) {
- Recipients recipients = RecipientFactory.getRecipientsFromString(getContext(),
- mediaRecord.getAddress(),
- true);
- if (recipients != null && recipients.getPrimaryRecipient() != null) {
- intent.putExtra(MediaPreviewActivity.RECIPIENT_EXTRA, recipients.getPrimaryRecipient().getRecipientId());
- }
+ if (mediaRecord.getAddress() != null) {
+ intent.putExtra(MediaPreviewActivity.ADDRESS_EXTRA, mediaRecord.getAddress());
}
+
intent.setDataAndType(mediaRecord.getAttachment().getDataUri(), mediaRecord.getContentType());
getContext().startActivity(intent);
}
diff --git a/src/org/thoughtcrime/securesms/MediaOverviewActivity.java b/src/org/thoughtcrime/securesms/MediaOverviewActivity.java
index 2552e08c16..8673fbb616 100644
--- a/src/org/thoughtcrime/securesms/MediaOverviewActivity.java
+++ b/src/org/thoughtcrime/securesms/MediaOverviewActivity.java
@@ -38,12 +38,12 @@ import android.view.WindowManager;
import android.widget.TextView;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord;
-import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
+import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.AbstractCursorLoader;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
@@ -58,7 +58,7 @@ import java.util.List;
public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity implements LoaderManager.LoaderCallbacks {
private final static String TAG = MediaOverviewActivity.class.getSimpleName();
- public static final String RECIPIENT_EXTRA = "recipient";
+ public static final String ADDRESSES_EXTRA = "addresses";
public static final String THREAD_ID_EXTRA = "thread_id";
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@@ -68,7 +68,7 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
private RecyclerView gridView;
private GridLayoutManager gridManager;
private TextView noImages;
- private Recipient recipient;
+ private Recipients recipients;
private long threadId;
@Override
@@ -113,9 +113,9 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
}
private void initializeActionBar() {
- getSupportActionBar().setTitle(recipient == null
+ getSupportActionBar().setTitle(recipients == null
? getString(R.string.AndroidManifest__all_media)
- : getString(R.string.AndroidManifest__all_media_named, recipient.toShortString()));
+ : getString(R.string.AndroidManifest__all_media_named, recipients.toShortString()));
}
@Override
@@ -132,19 +132,20 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
gridView.setLayoutManager(gridManager);
gridView.setHasFixedSize(true);
- final long recipientId = getIntent().getLongExtra(RECIPIENT_EXTRA, -1);
- if (recipientId > -1) {
- recipient = RecipientFactory.getRecipientForId(this, recipientId, true);
- } else if (threadId > -1){
- recipient = DatabaseFactory.getThreadDatabase(this).getRecipientsForThreadId(threadId).getPrimaryRecipient();
+ Address[] addresses = Address.fromParcelable(getIntent().getParcelableArrayExtra(ADDRESSES_EXTRA));
+
+ if (addresses != null) {
+ recipients = RecipientFactory.getRecipientsFor(this, addresses, true);
+ } else if (threadId > -1) {
+ recipients = DatabaseFactory.getThreadDatabase(this).getRecipientsForThreadId(threadId);
} else {
- recipient = null;
+ recipients = null;
}
- if (recipient != null) {
- recipient.addListener(new RecipientModifiedListener() {
+ if (recipients != null) {
+ recipients.addListener(new Recipients.RecipientsModifiedListener() {
@Override
- public void onModified(Recipient recipient) {
+ public void onModified(Recipients recipients) {
initializeActionBar();
}
});
diff --git a/src/org/thoughtcrime/securesms/MediaPreviewActivity.java b/src/org/thoughtcrime/securesms/MediaPreviewActivity.java
index f56673fb92..be35e09c7e 100644
--- a/src/org/thoughtcrime/securesms/MediaPreviewActivity.java
+++ b/src/org/thoughtcrime/securesms/MediaPreviewActivity.java
@@ -34,6 +34,7 @@ import android.widget.Toast;
import org.thoughtcrime.securesms.components.ZoomingImageView;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.mms.VideoSlide;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener;
@@ -52,7 +53,7 @@ import java.io.IOException;
public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener {
private final static String TAG = MediaPreviewActivity.class.getSimpleName();
- public static final String RECIPIENT_EXTRA = "recipient";
+ public static final String ADDRESS_EXTRA = "address";
public static final String THREAD_ID_EXTRA = "thread_id";
public static final String DATE_EXTRA = "date";
public static final String SIZE_EXTRA = "size";
@@ -143,7 +144,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
}
private void initializeResources() {
- final long recipientId = getIntent().getLongExtra(RECIPIENT_EXTRA, -1);
+ Address address = getIntent().getParcelableExtra(ADDRESS_EXTRA);
mediaUri = getIntent().getData();
mediaType = getIntent().getType();
@@ -151,8 +152,8 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
size = getIntent().getLongExtra(SIZE_EXTRA, 0);
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
- if (recipientId > -1) {
- recipient = RecipientFactory.getRecipientForId(this, recipientId, true);
+ if (address != null) {
+ recipient = RecipientFactory.getRecipientFor(this, address, true);
recipient.addListener(this);
} else {
recipient = null;
diff --git a/src/org/thoughtcrime/securesms/MessageDetailsActivity.java b/src/org/thoughtcrime/securesms/MessageDetailsActivity.java
index 8e96c42463..b518ab9f0d 100644
--- a/src/org/thoughtcrime/securesms/MessageDetailsActivity.java
+++ b/src/org/thoughtcrime/securesms/MessageDetailsActivity.java
@@ -36,6 +36,7 @@ import android.widget.TextView;
import org.thoughtcrime.securesms.color.MaterialColor;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.MmsDatabase;
@@ -73,7 +74,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
public final static String THREAD_ID_EXTRA = "thread_id";
public final static String IS_PUSH_GROUP_EXTRA = "is_push_group";
public final static String TYPE_EXTRA = "type";
- public final static String RECIPIENTS_IDS_EXTRA = "recipients_ids";
+ public final static String ADDRESSES_EXTRA = "addresses";
private MasterSecret masterSecret;
private long threadId;
@@ -138,7 +139,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
private void initializeActionBar() {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- Recipients recipients = RecipientFactory.getRecipientsForIds(this, getIntent().getLongArrayExtra(RECIPIENTS_IDS_EXTRA), true);
+ Recipients recipients = RecipientFactory.getRecipientsFor(this, Address.fromParcelable(getIntent().getParcelableArrayExtra(ADDRESSES_EXTRA)), true);
recipients.addListener(this);
setActionBarColor(recipients.getColor());
@@ -355,9 +356,9 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
recipients = intermediaryRecipients;
} else {
try {
- String groupId = intermediaryRecipients.getPrimaryRecipient().getNumber();
+ Address groupId = intermediaryRecipients.getPrimaryRecipient().getAddress();
recipients = DatabaseFactory.getGroupDatabase(context)
- .getGroupMembers(GroupUtil.getDecodedId(groupId), false);
+ .getGroupMembers(GroupUtil.getDecodedId(groupId.toGroupString()), false);
} catch (IOException e) {
Log.w(TAG, e);
recipients = RecipientFactory.getRecipientsFor(MessageDetailsActivity.this, new LinkedList(), false);
diff --git a/src/org/thoughtcrime/securesms/MessageDetailsRecipientAdapter.java b/src/org/thoughtcrime/securesms/MessageDetailsRecipientAdapter.java
index a908c8295b..a0e39aa0e7 100644
--- a/src/org/thoughtcrime/securesms/MessageDetailsRecipientAdapter.java
+++ b/src/org/thoughtcrime/securesms/MessageDetailsRecipientAdapter.java
@@ -11,6 +11,10 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
+import org.thoughtcrime.securesms.util.Conversions;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
public class MessageDetailsRecipientAdapter extends BaseAdapter implements AbsListView.RecyclerListener {
@@ -43,7 +47,11 @@ public class MessageDetailsRecipientAdapter extends BaseAdapter implements AbsLi
@Override
public long getItemId(int position) {
- return recipients.getRecipientsList().get(position).getRecipientId();
+ try {
+ return Conversions.byteArrayToLong(MessageDigest.getInstance("SHA1").digest(recipients.getRecipientsList().get(position).getAddress().serialize().getBytes()));
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
}
@Override
diff --git a/src/org/thoughtcrime/securesms/MessageRecipientListItem.java b/src/org/thoughtcrime/securesms/MessageRecipientListItem.java
index c6b80dfcf2..8d2d5715d7 100644
--- a/src/org/thoughtcrime/securesms/MessageRecipientListItem.java
+++ b/src/org/thoughtcrime/securesms/MessageRecipientListItem.java
@@ -137,7 +137,7 @@ public class MessageRecipientListItem extends RelativeLayout
private NetworkFailure getNetworkFailure(final MessageRecord record) {
if (record.hasNetworkFailures()) {
for (final NetworkFailure failure : record.getNetworkFailures()) {
- if (failure.getRecipientId() == recipient.getRecipientId()) {
+ if (failure.getAddress().equals(recipient.getAddress())) {
return failure;
}
}
@@ -148,7 +148,7 @@ public class MessageRecipientListItem extends RelativeLayout
private IdentityKeyMismatch getKeyMismatch(final MessageRecord record) {
if (record.isIdentityMismatchFailure()) {
for (final IdentityKeyMismatch mismatch : record.getIdentityKeyMismatches()) {
- if (mismatch.getRecipientId() == recipient.getRecipientId()) {
+ if (mismatch.getAddress().equals(recipient.getAddress())) {
return mismatch;
}
}
@@ -188,7 +188,7 @@ public class MessageRecipientListItem extends RelativeLayout
mmsDatabase.removeFailure(record.getId(), failure);
if (record.getRecipients().isGroupRecipient()) {
- MessageSender.resendGroupMessage(getContext(), masterSecret, record, failure.getRecipientId());
+ MessageSender.resendGroupMessage(getContext(), masterSecret, record, failure.getAddress());
} else {
MessageSender.resend(getContext(), masterSecret, record);
}
diff --git a/src/org/thoughtcrime/securesms/NewConversationActivity.java b/src/org/thoughtcrime/securesms/NewConversationActivity.java
index f9c72c615f..2d43a2631d 100644
--- a/src/org/thoughtcrime/securesms/NewConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/NewConversationActivity.java
@@ -25,6 +25,7 @@ import android.view.MenuItem;
import android.view.View;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
@@ -49,10 +50,10 @@ public class NewConversationActivity extends ContactSelectionActivity {
@Override
public void onContactSelected(String number) {
- Recipients recipients = RecipientFactory.getRecipientsFromString(this, number, true);
+ Recipients recipients = RecipientFactory.getRecipientsFor(this, new Address[] {Address.fromExternal(this, number)}, true);
Intent intent = new Intent(this, ConversationActivity.class);
- intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds());
+ intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
intent.putExtra(ConversationActivity.TEXT_EXTRA, getIntent().getStringExtra(ConversationActivity.TEXT_EXTRA));
intent.setDataAndType(getIntent().getData(), getIntent().getType());
diff --git a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
index 7b844b0f0b..849891afb7 100644
--- a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
+++ b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
@@ -31,6 +31,7 @@ import org.thoughtcrime.securesms.color.MaterialColors;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.IdentityDatabase;
@@ -48,7 +49,6 @@ import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
-import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.util.guava.Optional;
import java.util.concurrent.ExecutionException;
@@ -57,7 +57,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
{
private static final String TAG = RecipientPreferenceActivity.class.getSimpleName();
- public static final String RECIPIENTS_EXTRA = "recipient_ids";
+ public static final String ADDRESSES_EXTRA = "recipient_addresses";
public static final String CAN_HAVE_SAFETY_NUMBER_EXTRA = "can_have_safety_number";
private static final String PREFERENCE_MUTED = "pref_key_recipient_mute";
@@ -86,8 +86,8 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
public void onCreate(Bundle instanceState, @NonNull MasterSecret masterSecret) {
setContentView(R.layout.recipient_preference_activity);
- long[] recipientIds = getIntent().getLongArrayExtra(RECIPIENTS_EXTRA);
- Recipients recipients = RecipientFactory.getRecipientsForIds(this, recipientIds, true);
+ Address[] addresses = Address.fromParcelable(getIntent().getParcelableArrayExtra(ADDRESSES_EXTRA));
+ Recipients recipients = RecipientFactory.getRecipientsFor(this, addresses, true);
initializeToolbar();
initializeReceivers();
@@ -95,7 +95,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
recipients.addListener(this);
Bundle bundle = new Bundle();
- bundle.putLongArray(RECIPIENTS_EXTRA, recipientIds);
+ bundle.putParcelableArray(ADDRESSES_EXTRA, addresses);
initFragment(R.id.preference_fragment, new RecipientPreferenceFragment(), masterSecret, null, bundle);
}
@@ -149,7 +149,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
this.staleReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- Recipients recipients = RecipientFactory.getRecipientsForIds(context, getIntent().getLongArrayExtra(RECIPIENTS_EXTRA), true);
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, Address.fromParcelable(getIntent().getParcelableArrayExtra(ADDRESSES_EXTRA)), true);
recipients.addListener(RecipientPreferenceActivity.this);
onModified(recipients);
}
@@ -234,9 +234,9 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
}
private void initializeRecipients() {
- this.recipients = RecipientFactory.getRecipientsForIds(getActivity(),
- getArguments().getLongArray(RECIPIENTS_EXTRA),
- true);
+ this.recipients = RecipientFactory.getRecipientsFor(getActivity(),
+ Address.fromParcelable(getArguments().getParcelableArray(ADDRESSES_EXTRA)),
+ true);
this.recipients.addListener(this);
@@ -244,7 +244,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
@Override
public void onReceive(Context context, Intent intent) {
recipients.removeListener(RecipientPreferenceFragment.this);
- recipients = RecipientFactory.getRecipientsForIds(getActivity(), getArguments().getLongArray(RECIPIENTS_EXTRA), true);
+ recipients = RecipientFactory.getRecipientsFor(getActivity(), Address.fromParcelable(getArguments().getParcelableArray(ADDRESSES_EXTRA)), true);
onModified(recipients);
}
};
@@ -411,7 +411,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
{
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new MultiDeviceContactUpdateJob(context, recipients.getPrimaryRecipient().getRecipientId()));
+ .add(new MultiDeviceContactUpdateJob(context, recipients.getPrimaryRecipient().getAddress()));
}
return null;
}
@@ -471,7 +471,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
@Override
public boolean onPreferenceClick(Preference preference) {
Intent verifyIdentityIntent = new Intent(getActivity(), VerifyIdentityActivity.class);
- verifyIdentityIntent.putExtra(VerifyIdentityActivity.RECIPIENT_ID_EXTRA, recipients.getPrimaryRecipient().getRecipientId());
+ verifyIdentityIntent.putExtra(VerifyIdentityActivity.ADDRESS_EXTRA, recipients.getPrimaryRecipient().getAddress());
verifyIdentityIntent.putExtra(VerifyIdentityActivity.IDENTITY_EXTRA, new IdentityKeyParcelable(identityKey.getIdentityKey()));
verifyIdentityIntent.putExtra(VerifyIdentityActivity.VERIFIED_EXTRA, identityKey.getVerifiedStatus() == IdentityDatabase.VerifiedStatus.VERIFIED);
startActivity(verifyIdentityIntent);
diff --git a/src/org/thoughtcrime/securesms/ShareActivity.java b/src/org/thoughtcrime/securesms/ShareActivity.java
index 0b8d2517cc..29466bd2de 100644
--- a/src/org/thoughtcrime/securesms/ShareActivity.java
+++ b/src/org/thoughtcrime/securesms/ShareActivity.java
@@ -23,6 +23,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Parcel;
import android.os.Process;
import android.provider.OpenableColumns;
import android.support.annotation.NonNull;
@@ -35,9 +36,9 @@ import android.view.View;
import android.view.ViewGroup;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
-import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
@@ -59,9 +60,9 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
{
private static final String TAG = ShareActivity.class.getSimpleName();
- public static final String EXTRA_THREAD_ID = "thread_id";
- public static final String EXTRA_RECIPIENT_IDS = "recipient_ids";
- public static final String EXTRA_DISTRIBUTION_TYPE = "distribution_type";
+ public static final String EXTRA_THREAD_ID = "thread_id";
+ public static final String EXTRA_ADDRESSES_MARSHALLED = "addresses";
+ public static final String EXTRA_DISTRIBUTION_TYPE = "distribution_type";
private final DynamicTheme dynamicTheme = new DynamicTheme ();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@@ -93,6 +94,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
@Override
protected void onNewIntent(Intent intent) {
+ Log.w(TAG, "onNewIntent()");
super.onNewIntent(intent);
setIntent(intent);
initializeMedia();
@@ -100,6 +102,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
@Override
public void onResume() {
+ Log.w(TAG, "onResume()");
super.onResume();
dynamicTheme.onResume(this);
dynamicLanguage.onResume(this);
@@ -163,15 +166,24 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
@Override
public void onCreateConversation(long threadId, Recipients recipients, int distributionType) {
- createConversation(threadId, recipients, distributionType);
+ createConversation(threadId, recipients.getAddresses(), distributionType);
}
private void handleResolvedMedia(Intent intent, boolean animate) {
- long threadId = intent.getLongExtra(EXTRA_THREAD_ID, -1);
- long[] recipientIds = intent.getLongArrayExtra(EXTRA_RECIPIENT_IDS);
- int distributionType = intent.getIntExtra(EXTRA_DISTRIBUTION_TYPE, -1);
+ long threadId = intent.getLongExtra(EXTRA_THREAD_ID, -1);
+ int distributionType = intent.getIntExtra(EXTRA_DISTRIBUTION_TYPE, -1);
+ Address[] addresses = null;
- boolean hasResolvedDestination = threadId != -1 && recipientIds != null && distributionType != -1;
+ if (intent.hasExtra(EXTRA_ADDRESSES_MARSHALLED)) {
+ Parcel parcel = Parcel.obtain();
+ byte[] marshalled = intent.getByteArrayExtra(EXTRA_ADDRESSES_MARSHALLED);
+ parcel.unmarshall(marshalled, 0, marshalled.length);
+ parcel.setDataPosition(0);
+ addresses = parcel.createTypedArray(Address.CREATOR);
+ parcel.recycle();
+ }
+
+ boolean hasResolvedDestination = threadId != -1 && addresses != null && distributionType != -1;
if (!hasResolvedDestination && animate) {
ViewUtil.fadeIn(fragmentContainer, 300);
@@ -180,13 +192,13 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
fragmentContainer.setVisibility(View.VISIBLE);
progressWheel.setVisibility(View.GONE);
} else {
- createConversation(threadId, RecipientFactory.getRecipientsForIds(this, recipientIds, true), distributionType);
+ createConversation(threadId, addresses, distributionType);
}
}
- private void createConversation(long threadId, Recipients recipients, int distributionType) {
+ private void createConversation(long threadId, Address[] addresses, int distributionType) {
final Intent intent = getBaseShareIntent(ConversationActivity.class);
- intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds());
+ intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, addresses);
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
diff --git a/src/org/thoughtcrime/securesms/SmsSendtoActivity.java b/src/org/thoughtcrime/securesms/SmsSendtoActivity.java
index 55bc8f5179..68fbcbd010 100644
--- a/src/org/thoughtcrime/securesms/SmsSendtoActivity.java
+++ b/src/org/thoughtcrime/securesms/SmsSendtoActivity.java
@@ -6,9 +6,11 @@ import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
+import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
@@ -38,19 +40,20 @@ public class SmsSendtoActivity extends Activity {
destination = getDestinationForView(original);
}
- Recipients recipients = RecipientFactory.getRecipientsFromString(this, destination.getDestination(), true);
- long threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients);
-
final Intent nextIntent;
- if (recipients.isEmpty()) {
+
+ if (TextUtils.isEmpty(destination.destination)) {
nextIntent = new Intent(this, NewConversationActivity.class);
nextIntent.putExtra(ConversationActivity.TEXT_EXTRA, destination.getBody());
Toast.makeText(this, R.string.ConversationActivity_specify_recipient, Toast.LENGTH_LONG).show();
} else {
+ Recipients recipients = RecipientFactory.getRecipientsFor(this, new Address[] {Address.fromExternal(this, destination.getDestination())}, true);
+ long threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients);
+
nextIntent = new Intent(this, ConversationActivity.class);
nextIntent.putExtra(ConversationActivity.TEXT_EXTRA, destination.getBody());
nextIntent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
- nextIntent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds());
+ nextIntent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
}
return nextIntent;
}
diff --git a/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java b/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java
index f13bf30871..f367d57518 100644
--- a/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java
+++ b/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java
@@ -65,6 +65,7 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
import org.thoughtcrime.securesms.jobs.MultiDeviceVerifiedUpdateJob;
@@ -84,7 +85,6 @@ import org.whispersystems.libsignal.fingerprint.Fingerprint;
import org.whispersystems.libsignal.fingerprint.FingerprintParsingException;
import org.whispersystems.libsignal.fingerprint.FingerprintVersionMismatchException;
import org.whispersystems.libsignal.fingerprint.NumericFingerprintGenerator;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
@@ -100,9 +100,9 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
private static final String TAG = VerifyIdentityActivity.class.getSimpleName();
- public static final String RECIPIENT_ID_EXTRA = "recipient_id";
- public static final String IDENTITY_EXTRA = "recipient_identity";
- public static final String VERIFIED_EXTRA = "verified_state";
+ public static final String ADDRESS_EXTRA = "address";
+ public static final String IDENTITY_EXTRA = "recipient_identity";
+ public static final String VERIFIED_EXTRA = "verified_state";
private final DynamicTheme dynamicTheme = new DynamicTheme();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@@ -118,31 +118,26 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
@Override
protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) {
- try {
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setTitle(R.string.AndroidManifest__verify_safety_number);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setTitle(R.string.AndroidManifest__verify_safety_number);
- Recipient recipient = RecipientFactory.getRecipientForId(this, getIntent().getLongExtra(RECIPIENT_ID_EXTRA, -1), true);
- recipient.addListener(this);
+ Recipient recipient = RecipientFactory.getRecipientFor(this, (Address)getIntent().getParcelableExtra(ADDRESS_EXTRA), true);
+ recipient.addListener(this);
- setActionBarNotificationBarColor(recipient.getColor());
+ setActionBarNotificationBarColor(recipient.getColor());
- Bundle extras = new Bundle();
- extras.putLong(VerifyDisplayFragment.REMOTE_RECIPIENT_ID, getIntent().getLongExtra(RECIPIENT_ID_EXTRA, -1));
- extras.putParcelable(VerifyDisplayFragment.REMOTE_IDENTITY, getIntent().getParcelableExtra(IDENTITY_EXTRA));
- extras.putString(VerifyDisplayFragment.REMOTE_NUMBER, Util.canonicalizeNumber(this, recipient.getNumber()));
- extras.putParcelable(VerifyDisplayFragment.LOCAL_IDENTITY, new IdentityKeyParcelable(IdentityKeyUtil.getIdentityKey(this)));
- extras.putString(VerifyDisplayFragment.LOCAL_NUMBER, TextSecurePreferences.getLocalNumber(this));
- extras.putBoolean(VerifyDisplayFragment.VERIFIED_STATE, getIntent().getBooleanExtra(VERIFIED_EXTRA, false));
+ Bundle extras = new Bundle();
+ extras.putParcelable(VerifyDisplayFragment.REMOTE_ADDRESS, getIntent().getParcelableExtra(ADDRESS_EXTRA));
+ extras.putParcelable(VerifyDisplayFragment.REMOTE_IDENTITY, getIntent().getParcelableExtra(IDENTITY_EXTRA));
+ extras.putString(VerifyDisplayFragment.REMOTE_NUMBER, recipient.getAddress().toPhoneString());
+ extras.putParcelable(VerifyDisplayFragment.LOCAL_IDENTITY, new IdentityKeyParcelable(IdentityKeyUtil.getIdentityKey(this)));
+ extras.putString(VerifyDisplayFragment.LOCAL_NUMBER, TextSecurePreferences.getLocalNumber(this));
+ extras.putBoolean(VerifyDisplayFragment.VERIFIED_STATE, getIntent().getBooleanExtra(VERIFIED_EXTRA, false));
- scanFragment.setScanListener(this);
- displayFragment.setClickListener(this);
+ scanFragment.setScanListener(this);
+ displayFragment.setClickListener(this);
- initFragment(android.R.id.content, displayFragment, masterSecret, dynamicLanguage.getCurrentLocale(), extras);
- } catch (InvalidNumberException e) {
- Log.w(TAG, e);
- finish();
- }
+ initFragment(android.R.id.content, displayFragment, masterSecret, dynamicLanguage.getCurrentLocale(), extras);
}
@Override
@@ -198,12 +193,12 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
public static class VerifyDisplayFragment extends Fragment implements Recipient.RecipientModifiedListener, CompoundButton.OnCheckedChangeListener {
- public static final String REMOTE_RECIPIENT_ID = "remote_recipient_id";
- public static final String REMOTE_NUMBER = "remote_number";
- public static final String REMOTE_IDENTITY = "remote_identity";
- public static final String LOCAL_IDENTITY = "local_identity";
- public static final String LOCAL_NUMBER = "local_number";
- public static final String VERIFIED_STATE = "verified_state";
+ public static final String REMOTE_ADDRESS = "remote_address";
+ public static final String REMOTE_NUMBER = "remote_number";
+ public static final String REMOTE_IDENTITY = "remote_identity";
+ public static final String LOCAL_IDENTITY = "local_identity";
+ public static final String LOCAL_NUMBER = "local_number";
+ public static final String VERIFIED_STATE = "verified_state";
private MasterSecret masterSecret;
private Recipient recipient;
@@ -263,12 +258,20 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
+ Address address = getArguments().getParcelable(REMOTE_ADDRESS);
+ IdentityKeyParcelable localIdentityParcelable = getArguments().getParcelable(LOCAL_IDENTITY);
+ IdentityKeyParcelable remoteIdentityParcelable = getArguments().getParcelable(REMOTE_IDENTITY);
+
+ if (address == null) throw new AssertionError("Address required");
+ if (localIdentityParcelable == null) throw new AssertionError("local identity required");
+ if (remoteIdentityParcelable == null) throw new AssertionError("remote identity required");
+
this.masterSecret = getArguments().getParcelable("master_secret");
this.localNumber = getArguments().getString(LOCAL_NUMBER);
- this.localIdentity = ((IdentityKeyParcelable)getArguments().getParcelable(LOCAL_IDENTITY)).get();
+ this.localIdentity = localIdentityParcelable.get();
this.remoteNumber = getArguments().getString(REMOTE_NUMBER);
- this.recipient = RecipientFactory.getRecipientForId(getActivity(), getArguments().getLong(REMOTE_RECIPIENT_ID), true);
- this.remoteIdentity = ((IdentityKeyParcelable)getArguments().getParcelable(REMOTE_IDENTITY)).get();
+ this.recipient = RecipientFactory.getRecipientFor(getActivity(), address, true);
+ this.remoteIdentity = remoteIdentityParcelable.get();
this.recipient.addListener(this);
@@ -589,15 +592,15 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
protected Void doInBackground(Recipient... params) {
synchronized (SESSION_LOCK) {
if (isChecked) {
- Log.w(TAG, "Saving identity: " + params[0].getRecipientId());
+ Log.w(TAG, "Saving identity: " + params[0].getAddress());
DatabaseFactory.getIdentityDatabase(getActivity())
- .saveIdentity(params[0].getRecipientId(),
+ .saveIdentity(params[0].getAddress(),
remoteIdentity,
VerifiedStatus.VERIFIED, false,
System.currentTimeMillis(), true);
} else {
DatabaseFactory.getIdentityDatabase(getActivity())
- .setVerified(params[0].getRecipientId(),
+ .setVerified(params[0].getAddress(),
remoteIdentity,
VerifiedStatus.DEFAULT);
}
@@ -605,7 +608,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
ApplicationContext.getInstance(getActivity())
.getJobManager()
.add(new MultiDeviceVerifiedUpdateJob(getActivity(),
- recipient.getNumber(),
+ recipient.getAddress(),
remoteIdentity,
isChecked ? VerifiedStatus.VERIFIED :
VerifiedStatus.DEFAULT));
diff --git a/src/org/thoughtcrime/securesms/WebRtcCallActivity.java b/src/org/thoughtcrime/securesms/WebRtcCallActivity.java
index 55d0bb7189..0546205c9a 100644
--- a/src/org/thoughtcrime/securesms/WebRtcCallActivity.java
+++ b/src/org/thoughtcrime/securesms/WebRtcCallActivity.java
@@ -258,11 +258,11 @@ public class WebRtcCallActivity extends Activity {
public void onClick(View v) {
synchronized (SESSION_LOCK) {
TextSecureIdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(WebRtcCallActivity.this);
- identityKeyStore.saveIdentity(new SignalProtocolAddress(recipient.getNumber(), 1), theirIdentity, true);
+ identityKeyStore.saveIdentity(new SignalProtocolAddress(recipient.getAddress().serialize(), 1), theirIdentity, true);
}
Intent intent = new Intent(WebRtcCallActivity.this, WebRtcCallService.class);
- intent.putExtra(WebRtcCallService.EXTRA_REMOTE_NUMBER, recipient.getNumber());
+ intent.putExtra(WebRtcCallService.EXTRA_REMOTE_ADDRESS, recipient.getAddress());
intent.setAction(WebRtcCallService.ACTION_OUTGOING_CALL);
startService(intent);
}
diff --git a/src/org/thoughtcrime/securesms/components/AvatarImageView.java b/src/org/thoughtcrime/securesms/components/AvatarImageView.java
index 6fc4ea17ee..230b535134 100644
--- a/src/org/thoughtcrime/securesms/components/AvatarImageView.java
+++ b/src/org/thoughtcrime/securesms/components/AvatarImageView.java
@@ -63,7 +63,11 @@ public class AvatarImageView extends ImageView {
ContactsContract.QuickContact.showQuickContact(getContext(), AvatarImageView.this, recipient.getContactUri(), ContactsContract.QuickContact.MODE_LARGE, null);
} else if (recipient != null) {
final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
- intent.putExtra(ContactsContract.Intents.Insert.PHONE, recipient.getNumber());
+ if (recipient.getAddress().isEmail()) {
+ intent.putExtra(ContactsContract.Intents.Insert.EMAIL, recipient.getAddress().toEmailString());
+ } else {
+ intent.putExtra(ContactsContract.Intents.Insert.PHONE, recipient.getAddress().toPhoneString());
+ }
intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
getContext().startActivity(intent);
}
diff --git a/src/org/thoughtcrime/securesms/components/PushRecipientsPanel.java b/src/org/thoughtcrime/securesms/components/PushRecipientsPanel.java
index 30ff3dbd9e..c49c16d320 100644
--- a/src/org/thoughtcrime/securesms/components/PushRecipientsPanel.java
+++ b/src/org/thoughtcrime/securesms/components/PushRecipientsPanel.java
@@ -18,31 +18,28 @@ package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
-import android.widget.AutoCompleteTextView;
import android.widget.RelativeLayout;
-import android.widget.TextView;
import org.thoughtcrime.securesms.R;
-import org.thoughtcrime.securesms.contacts.ContactAccessor;
import org.thoughtcrime.securesms.contacts.RecipientsAdapter;
import org.thoughtcrime.securesms.contacts.RecipientsEditor;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.recipients.Recipients.RecipientsModifiedListener;
-import java.util.HashSet;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
+import java.util.StringTokenizer;
/**
* Panel component combining both an editable field with a button for
@@ -74,26 +71,11 @@ public class PushRecipientsPanel extends RelativeLayout implements RecipientsMod
initialize();
}
- public void addRecipient(String name, String number) {
- if (name != null) recipientsText.append(name + "< " + number + ">, ");
- else recipientsText.append(number + ", ");
- }
-
- public void addRecipients(Recipients recipients) {
- List recipientList = recipients.getRecipientsList();
- Iterator iterator = recipientList.iterator();
-
- while (iterator.hasNext()) {
- Recipient recipient = iterator.next();
- addRecipient(recipient.getName(), recipient.getNumber());
- }
- }
-
public Recipients getRecipients() throws RecipientFormattingException {
- String rawText = recipientsText.getText().toString();
- Recipients recipients = RecipientFactory.getRecipientsFromString(getContext(), rawText, true);
+ String rawText = recipientsText.getText().toString();
+ Recipients recipients = getRecipientsFromString(getContext(), rawText, true);
- if (recipients.isEmpty())
+ if (recipients == null || recipients.isEmpty())
throw new RecipientFormattingException("Recipient List Is Empty!");
return recipients;
@@ -151,7 +133,40 @@ public class PushRecipientsPanel extends RelativeLayout implements RecipientsMod
});
}
- @Override public void onModified(Recipients recipients) {
+ private @Nullable Recipients getRecipientsFromString(Context context, @NonNull String rawText, boolean asynchronous) {
+ StringTokenizer tokenizer = new StringTokenizer(rawText, ",");
+ List addresses = new LinkedList<>();
+
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken().trim();
+
+ if (!TextUtils.isEmpty(token)) {
+ if (hasBracketedNumber(token)) addresses.add(Address.fromExternal(context, parseBracketedNumber(token)));
+ else addresses.add(Address.fromExternal(context, token));
+ }
+ }
+
+ if (addresses.size() == 0) return null;
+ else return RecipientFactory.getRecipientsFor(context, addresses.toArray(new Address[0]), asynchronous);
+ }
+
+ private boolean hasBracketedNumber(String recipient) {
+ int openBracketIndex = recipient.indexOf('<');
+
+ return (openBracketIndex != -1) &&
+ (recipient.indexOf('>', openBracketIndex) != -1);
+ }
+
+ private String parseBracketedNumber(String recipient) {
+ int begin = recipient.indexOf('<');
+ int end = recipient.indexOf('>', begin);
+ String value = recipient.substring(begin + 1, end);
+
+ return value;
+ }
+
+ @Override
+ public void onModified(Recipients recipients) {
recipientsText.populate(recipients);
}
diff --git a/src/org/thoughtcrime/securesms/components/SingleRecipientPanel.java b/src/org/thoughtcrime/securesms/components/SingleRecipientPanel.java
deleted file mode 100644
index 1685ad75c3..0000000000
--- a/src/org/thoughtcrime/securesms/components/SingleRecipientPanel.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- * Copyright (C) 2011 Whisper Systems
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.thoughtcrime.securesms.components;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.RelativeLayout;
-
-import org.thoughtcrime.securesms.R;
-import org.thoughtcrime.securesms.contacts.ContactAccessor;
-import org.thoughtcrime.securesms.contacts.RecipientsAdapter;
-import org.thoughtcrime.securesms.contacts.RecipientsEditor;
-import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.recipients.RecipientFactory;
-import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
-import org.thoughtcrime.securesms.recipients.Recipients;
-import org.thoughtcrime.securesms.recipients.Recipients.RecipientsModifiedListener;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Panel component combining both an editable field with a button for
- * a list-based contact selector.
- *
- * @author Moxie Marlinspike
- */
-public class SingleRecipientPanel extends RelativeLayout implements RecipientsModifiedListener {
- private final String TAG = SingleRecipientPanel.class.getSimpleName();
- private RecipientsPanelChangedListener panelChangeListener;
-
- private RecipientsEditor recipientsText;
- private View panel;
-
- private static final int RECIPIENTS_MAX_LENGTH = 312;
-
- public SingleRecipientPanel(Context context) {
- super(context);
- initialize();
- }
-
- public SingleRecipientPanel(Context context, AttributeSet attrs) {
- super(context, attrs);
- initialize();
- }
-
- public SingleRecipientPanel(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initialize();
- }
-
- public void addRecipient(String name, String number) {
- Log.i(TAG, "addRecipient for " + name + "/" + number);
- if (name != null) recipientsText.append(name + "< " + number + ">, ");
- else recipientsText.append(number + ", ");
- }
-
- public void addRecipients(Recipients recipients) {
- List recipientList = recipients.getRecipientsList();
- Iterator iterator = recipientList.iterator();
-
- while (iterator.hasNext()) {
- Recipient recipient = iterator.next();
- addRecipient(recipient.getName(), recipient.getNumber());
- }
- }
-
- public void addContacts(List contacts) {
- for (ContactAccessor.ContactData contact : contacts) {
- for (ContactAccessor.NumberData number : contact.numbers) {
- addRecipient(contact.name, number.number);
- }
- }
- }
-
- public Recipients getRecipients() throws RecipientFormattingException {
- String rawText = recipientsText.getText().toString();
- Recipients recipients = RecipientFactory.getRecipientsFromString(getContext(), rawText, true);
-
- if (recipients.isEmpty())
- throw new RecipientFormattingException("Recipient List Is Empty!");
-
- return recipients;
- }
-
- public void disable() {
- clear();
- panel.setVisibility(View.GONE);
- }
-
- public void clear() {
- recipientsText.setText("");
- }
-
- public void setPanelChangeListener(RecipientsPanelChangedListener panelChangeListener) {
- this.panelChangeListener = panelChangeListener;
- }
-
- private void initialize() {
- LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.single_recipient_panel, this, true);
-
- panel = findViewById(R.id.recipients_panel);
- initRecipientsEditor();
- }
-
- private void initRecipientsEditor() {
- Recipients recipients;
- recipientsText = (RecipientsEditor)findViewById(R.id.recipients_text);
-
- try {
- recipients = getRecipients();
- } catch (RecipientFormattingException e) {
- recipients = RecipientFactory.getRecipientsFor(getContext(), new LinkedList(), true);
- }
- recipients.addListener(this);
-
- recipientsText.setAdapter(new RecipientsAdapter(this.getContext()));
- recipientsText.populate(recipients);
-
- recipientsText.setOnFocusChangeListener(new FocusChangedListener());
- recipientsText.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
- if (panelChangeListener != null) {
- try {
- panelChangeListener.onRecipientsPanelUpdate(getRecipients());
- } catch (RecipientFormattingException rfe) {
- panelChangeListener.onRecipientsPanelUpdate(null);
- }
- }
- recipientsText.setText("");
- }
- });
- }
-
- @Override public void onModified(Recipients recipients) {
- recipientsText.populate(recipients);
- }
-
- private class FocusChangedListener implements OnFocusChangeListener {
- public void onFocusChange(View v, boolean hasFocus) {
- if (!hasFocus && (panelChangeListener != null)) {
- try {
- panelChangeListener.onRecipientsPanelUpdate(getRecipients());
- } catch (RecipientFormattingException rfe) {
- panelChangeListener.onRecipientsPanelUpdate(null);
- }
- }
- }
- }
-
- public interface RecipientsPanelChangedListener {
- public void onRecipientsPanelUpdate(Recipients recipients);
- }
-
-}
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/components/identity/UntrustedSendDialog.java b/src/org/thoughtcrime/securesms/components/identity/UntrustedSendDialog.java
index 0bd6268a4b..45ac6472ba 100644
--- a/src/org/thoughtcrime/securesms/components/identity/UntrustedSendDialog.java
+++ b/src/org/thoughtcrime/securesms/components/identity/UntrustedSendDialog.java
@@ -46,7 +46,7 @@ public class UntrustedSendDialog extends AlertDialog.Builder implements DialogIn
protected Void doInBackground(Void... params) {
synchronized (SESSION_LOCK) {
for (IdentityRecord identityRecord : untrustedRecords) {
- identityDatabase.setApproval(identityRecord.getRecipientId(), true);
+ identityDatabase.setApproval(identityRecord.getAddress(), true);
}
}
diff --git a/src/org/thoughtcrime/securesms/components/identity/UnverifiedSendDialog.java b/src/org/thoughtcrime/securesms/components/identity/UnverifiedSendDialog.java
index bf1e0cf300..9bf6e3cc27 100644
--- a/src/org/thoughtcrime/securesms/components/identity/UnverifiedSendDialog.java
+++ b/src/org/thoughtcrime/securesms/components/identity/UnverifiedSendDialog.java
@@ -45,7 +45,7 @@ public class UnverifiedSendDialog extends AlertDialog.Builder implements DialogI
protected Void doInBackground(Void... params) {
synchronized (SESSION_LOCK) {
for (IdentityRecord identityRecord : untrustedRecords) {
- identityDatabase.setVerified(identityRecord.getRecipientId(),
+ identityDatabase.setVerified(identityRecord.getAddress(),
identityRecord.getIdentityKey(),
IdentityDatabase.VerifiedStatus.DEFAULT);
}
diff --git a/src/org/thoughtcrime/securesms/components/webrtc/WebRtcCallScreen.java b/src/org/thoughtcrime/securesms/components/webrtc/WebRtcCallScreen.java
index 35db803b2b..5de9769da7 100644
--- a/src/org/thoughtcrime/securesms/components/webrtc/WebRtcCallScreen.java
+++ b/src/org/thoughtcrime/securesms/components/webrtc/WebRtcCallScreen.java
@@ -120,7 +120,7 @@ public class WebRtcCallScreen extends FrameLayout implements Recipient.Recipient
String introduction = String.format(getContext().getString(R.string.WebRtcCallScreen_new_safety_numbers), name, name);
SpannableString spannableString = new SpannableString(introduction + " " + getContext().getString(R.string.WebRtcCallScreen_you_may_wish_to_verify_this_contact));
- spannableString.setSpan(new VerifySpan(getContext(), personInfo.getRecipientId(), untrustedIdentity),
+ spannableString.setSpan(new VerifySpan(getContext(), personInfo.getAddress(), untrustedIdentity),
introduction.length()+1, spannableString.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -302,7 +302,7 @@ public class WebRtcCallScreen extends FrameLayout implements Recipient.Recipient
}.execute();
this.name.setText(recipient.getName());
- this.phoneNumber.setText(recipient.getNumber());
+ this.phoneNumber.setText(recipient.getAddress().serialize());
}
private void setCard(Recipient recipient, String status) {
diff --git a/src/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java b/src/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java
index 0790bb6402..34ab6014de 100644
--- a/src/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java
+++ b/src/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java
@@ -10,9 +10,10 @@ import android.widget.TextView;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.AvatarImageView;
-import org.thoughtcrime.securesms.recipients.Recipient;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
+import org.thoughtcrime.securesms.recipients.RecipientsFormatter;
import org.thoughtcrime.securesms.util.ViewUtil;
public class ContactSelectionListItem extends LinearLayout implements Recipients.RecipientsModifiedListener {
@@ -53,9 +54,10 @@ public class ContactSelectionListItem extends LinearLayout implements Recipients
if (type == ContactsDatabase.NEW_TYPE) {
this.recipients = null;
- this.contactPhotoImage.setAvatar(Recipient.getUnknownRecipient(), false);
+ this.contactPhotoImage.setAvatar(RecipientFactory.getRecipientFor(getContext(), Address.UNKNOWN, true), false);
} else if (!TextUtils.isEmpty(number)) {
- this.recipients = RecipientFactory.getRecipientsFromString(getContext(), number, true);
+ Address address = Address.fromExternal(getContext(), number);
+ this.recipients = RecipientFactory.getRecipientsFor(getContext(), new Address[] {address}, true);
if (this.recipients.getPrimaryRecipient() != null &&
this.recipients.getPrimaryRecipient().getName() != null)
diff --git a/src/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java b/src/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java
index 4554cb3ede..59a5f8ada4 100644
--- a/src/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java
+++ b/src/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java
@@ -27,6 +27,7 @@ import android.text.TextUtils;
import android.util.Log;
import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
@@ -102,8 +103,8 @@ public class ContactsCursorLoader extends CursorLoader {
ContactsDatabase.LABEL_COLUMN,
ContactsDatabase.CONTACT_TYPE_COLUMN});
while (cursor.moveToNext()) {
- final String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_COLUMN));
- final Recipients recipients = RecipientFactory.getRecipientsFromString(getContext(), number, true);
+ final String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_COLUMN));
+ final Recipients recipients = RecipientFactory.getRecipientsFor(getContext(), new Address[]{Address.fromExternal(getContext(), number)}, true);
if (DirectoryHelper.getUserCapabilities(getContext(), recipients)
.getTextCapability() != Capability.SUPPORTED)
diff --git a/src/org/thoughtcrime/securesms/contacts/RecipientsEditor.java b/src/org/thoughtcrime/securesms/contacts/RecipientsEditor.java
index deea9f924c..23c6c39f50 100644
--- a/src/org/thoughtcrime/securesms/contacts/RecipientsEditor.java
+++ b/src/org/thoughtcrime/securesms/contacts/RecipientsEditor.java
@@ -128,9 +128,9 @@ public class RecipientsEditor extends AppCompatMultiAutoCompleteTextView {
return mTokenizer.getNumbers();
}
- public Recipients constructContactsFromInput() {
- return RecipientFactory.getRecipientsFromString(mContext, mTokenizer.getRawString(), false);
- }
+// public Recipients constructContactsFromInput() {
+// return RecipientFactory.getRecipientsFromString(mContext, mTokenizer.getRawString(), false);
+// }
private boolean isValidAddress(String number, boolean isMms) {
/*if (isMms) {
@@ -191,7 +191,7 @@ public class RecipientsEditor extends AppCompatMultiAutoCompleteTextView {
public static CharSequence contactToToken(Recipient c) {
String name = c.getName();
- String number = c.getNumber();
+ String number = c.getAddress().serialize();
SpannableString s = new SpannableString(RecipientsFormatter.formatNameAndNumber(name, number));
int len = s.length();
@@ -199,7 +199,7 @@ public class RecipientsEditor extends AppCompatMultiAutoCompleteTextView {
return s;
}
- s.setSpan(new Annotation("number", c.getNumber()), 0, len,
+ s.setSpan(new Annotation("number", c.getAddress().serialize()), 0, len,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return s;
diff --git a/src/org/thoughtcrime/securesms/crypto/SessionUtil.java b/src/org/thoughtcrime/securesms/crypto/SessionUtil.java
index 86fbc4565a..8d4a616492 100644
--- a/src/org/thoughtcrime/securesms/crypto/SessionUtil.java
+++ b/src/org/thoughtcrime/securesms/crypto/SessionUtil.java
@@ -4,6 +4,7 @@ import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.whispersystems.libsignal.SignalProtocolAddress;
import org.whispersystems.libsignal.state.SessionRecord;
@@ -15,12 +16,12 @@ import java.util.List;
public class SessionUtil {
public static boolean hasSession(Context context, MasterSecret masterSecret, Recipient recipient) {
- return hasSession(context, masterSecret, recipient.getNumber());
+ return hasSession(context, masterSecret, recipient.getAddress());
}
- public static boolean hasSession(Context context, MasterSecret masterSecret, @NonNull String number) {
+ public static boolean hasSession(Context context, MasterSecret masterSecret, @NonNull Address address) {
SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret);
- SignalProtocolAddress axolotlAddress = new SignalProtocolAddress(number, SignalServiceAddress.DEFAULT_DEVICE_ID);
+ SignalProtocolAddress axolotlAddress = new SignalProtocolAddress(address.serialize(), SignalServiceAddress.DEFAULT_DEVICE_ID);
return sessionStore.containsSession(axolotlAddress);
}
diff --git a/src/org/thoughtcrime/securesms/crypto/storage/TextSecureIdentityKeyStore.java b/src/org/thoughtcrime/securesms/crypto/storage/TextSecureIdentityKeyStore.java
index 68f1dbfa9f..1279349b64 100644
--- a/src/org/thoughtcrime/securesms/crypto/storage/TextSecureIdentityKeyStore.java
+++ b/src/org/thoughtcrime/securesms/crypto/storage/TextSecureIdentityKeyStore.java
@@ -5,12 +5,12 @@ import android.util.Log;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.crypto.SessionUtil;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
-import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.IdentityKey;
@@ -47,13 +47,12 @@ public class TextSecureIdentityKeyStore implements IdentityKeyStore {
public boolean saveIdentity(SignalProtocolAddress address, IdentityKey identityKey, boolean nonBlockingApproval) {
synchronized (LOCK) {
IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(context);
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, address.getName(), true);
- long recipientId = recipients.getPrimaryRecipient().getRecipientId();
- Optional identityRecord = identityDatabase.getIdentity(recipientId);
+ Address signalAddress = Address.fromExternal(context, address.getName());
+ Optional identityRecord = identityDatabase.getIdentity(signalAddress);
if (!identityRecord.isPresent()) {
Log.w(TAG, "Saving new identity...");
- identityDatabase.saveIdentity(recipientId, identityKey, VerifiedStatus.DEFAULT, true, System.currentTimeMillis(), nonBlockingApproval);
+ identityDatabase.saveIdentity(signalAddress, identityKey, VerifiedStatus.DEFAULT, true, System.currentTimeMillis(), nonBlockingApproval);
return false;
}
@@ -69,15 +68,15 @@ public class TextSecureIdentityKeyStore implements IdentityKeyStore {
verifiedStatus = VerifiedStatus.DEFAULT;
}
- identityDatabase.saveIdentity(recipientId, identityKey, verifiedStatus, false, System.currentTimeMillis(), nonBlockingApproval);
- IdentityUtil.markIdentityUpdate(context, recipients.getPrimaryRecipient());
+ identityDatabase.saveIdentity(signalAddress, identityKey, verifiedStatus, false, System.currentTimeMillis(), nonBlockingApproval);
+ IdentityUtil.markIdentityUpdate(context, RecipientFactory.getRecipientFor(context, signalAddress, true));
SessionUtil.archiveSiblingSessions(context, address);
return true;
}
if (isNonBlockingApprovalRequired(identityRecord.get())) {
Log.w(TAG, "Setting approval status...");
- identityDatabase.setApproval(recipientId, nonBlockingApproval);
+ identityDatabase.setApproval(signalAddress, nonBlockingApproval);
return false;
}
@@ -94,16 +93,15 @@ public class TextSecureIdentityKeyStore implements IdentityKeyStore {
public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) {
synchronized (LOCK) {
IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(context);
- long recipientId = RecipientFactory.getRecipientsFromString(context, address.getName(), true).getPrimaryRecipient().getRecipientId();
String ourNumber = TextSecurePreferences.getLocalNumber(context);
- long ourRecipientId = RecipientFactory.getRecipientsFromString(context, ourNumber, true).getPrimaryRecipient().getRecipientId();
+ Address theirAddress = Address.fromExternal(context, address.getName());
- if (ourRecipientId == recipientId || ourNumber.equals(address.getName())) {
+ if (ourNumber.equals(address.getName()) || Address.fromSerialized(ourNumber).equals(theirAddress)) {
return identityKey.equals(IdentityKeyUtil.getIdentityKey(context));
}
switch (direction) {
- case SENDING: return isTrustedForSending(identityKey, identityDatabase.getIdentity(recipientId));
+ case SENDING: return isTrustedForSending(identityKey, identityDatabase.getIdentity(theirAddress));
case RECEIVING: return true;
default: throw new AssertionError("Unknown direction: " + direction);
}
diff --git a/src/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java b/src/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java
index 93eb7a037b..389869e3c2 100644
--- a/src/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java
+++ b/src/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java
@@ -7,11 +7,9 @@ import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterCipher;
import org.thoughtcrime.securesms.crypto.MasterSecret;
-import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.util.Conversions;
-import org.whispersystems.libsignal.SignalProtocolAddress;
import org.whispersystems.libsignal.InvalidMessageException;
+import org.whispersystems.libsignal.SignalProtocolAddress;
import org.whispersystems.libsignal.protocol.CiphertextMessage;
import org.whispersystems.libsignal.state.SessionRecord;
import org.whispersystems.libsignal.state.SessionState;
@@ -135,7 +133,6 @@ public class TextSecureSessionStore implements SessionStore {
@Override
public List getSubDeviceSessions(String name) {
- long recipientId = RecipientFactory.getRecipientsFromString(context, name, true).getPrimaryRecipient().getRecipientId();
List results = new LinkedList<>();
File parent = getSessionDirectory();
String[] children = parent.list();
@@ -144,10 +141,10 @@ public class TextSecureSessionStore implements SessionStore {
for (String child : children) {
try {
- String[] parts = child.split("[.]", 2);
- long sessionRecipientId = Long.parseLong(parts[0]);
+ String[] parts = child.split("[.]", 2);
+ String sessionName = parts[0];
- if (sessionRecipientId == recipientId && parts.length > 1) {
+ if (sessionName.equals(name) && parts.length > 1) {
results.add(Integer.parseInt(parts[1]));
}
} catch (NumberFormatException e) {
@@ -209,26 +206,21 @@ public class TextSecureSessionStore implements SessionStore {
return directory;
}
- private String getSessionName(SignalProtocolAddress axolotlAddress) {
- Recipient recipient = RecipientFactory.getRecipientsFromString(context, axolotlAddress.getName(), true)
- .getPrimaryRecipient();
- long recipientId = recipient.getRecipientId();
- int deviceId = axolotlAddress.getDeviceId();
-
- return recipientId + (deviceId == SignalServiceAddress.DEFAULT_DEVICE_ID ? "" : "." + deviceId);
+ private String getSessionName(SignalProtocolAddress address) {
+ int deviceId = address.getDeviceId();
+ return address.getName() + (deviceId == SignalServiceAddress.DEFAULT_DEVICE_ID ? "" : "." + deviceId);
}
private @Nullable SignalProtocolAddress getAddressName(File sessionFile) {
try {
- String[] parts = sessionFile.getName().split("[.]");
- Recipient recipient = RecipientFactory.getRecipientForId(context, Integer.valueOf(parts[0]), true);
+ String[] parts = sessionFile.getName().split("[.]");
int deviceId;
if (parts.length > 1) deviceId = Integer.parseInt(parts[1]);
else deviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
- return new SignalProtocolAddress(recipient.getNumber(), deviceId);
+ return new SignalProtocolAddress(parts[0], deviceId);
} catch (NumberFormatException e) {
Log.w(TAG, e);
return null;
diff --git a/src/org/thoughtcrime/securesms/database/Address.java b/src/org/thoughtcrime/securesms/database/Address.java
new file mode 100644
index 0000000000..69d49a39fa
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/database/Address.java
@@ -0,0 +1,156 @@
+package org.thoughtcrime.securesms.database;
+
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.util.Log;
+
+import org.thoughtcrime.securesms.util.GroupUtil;
+import org.thoughtcrime.securesms.util.NumberUtil;
+import org.thoughtcrime.securesms.util.ShortCodeUtil;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
+import org.thoughtcrime.securesms.util.Util;
+import org.whispersystems.signalservice.api.util.InvalidNumberException;
+import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class Address implements Parcelable, Comparable {
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+ public Address createFromParcel(Parcel in) {
+ return new Address(in);
+ }
+
+ public Address[] newArray(int size) {
+ return new Address[size];
+ }
+ };
+
+ public static final Address UNKNOWN = new Address("Unknown");
+
+ private static final String TAG = Address.class.getSimpleName();
+
+ private final String address;
+
+ private Address(@NonNull String address) {
+ if (address == null) throw new AssertionError(address);
+ this.address = address;
+ }
+
+ public Address(Parcel in) {
+ this(in.readString());
+ }
+
+ public static Address fromSerialized(@NonNull String serialized) {
+ return new Address(serialized);
+ }
+
+ public static List fromSerializedList(@NonNull String serialized, @NonNull String delimiter) {
+ List elements = Util.split(serialized, delimiter);
+ List addresses = new LinkedList<>();
+
+ for (String element : elements) {
+ addresses.add(Address.fromSerialized(element));
+ }
+
+ return addresses;
+ }
+
+ public static Address fromExternal(@NonNull Context context, @Nullable String external)
+ {
+ if (external == null) return new Address("Unknown");
+
+ try {
+ String localNumber = TextSecurePreferences.getLocalNumber(context);
+
+ if (GroupUtil.isEncodedGroup(external)) return new Address(external);
+ else if (NumberUtil.isValidEmail(external)) return new Address(external);
+ else if (ShortCodeUtil.isShortCode(localNumber, external)) return new Address(external.replaceAll("[^0-9+]", ""));
+
+ return new Address(PhoneNumberFormatter.formatNumber(external, localNumber));
+ } catch (InvalidNumberException e) {
+ Log.w(TAG, e);
+ if (TextUtils.isEmpty(external.trim())) return new Address("Unknown");
+ else return new Address(external.trim());
+ }
+ }
+
+ public static Address[] fromParcelable(Parcelable[] parcelables) {
+ Address[] addresses = new Address[parcelables.length];
+
+ for (int i=0;i.
- */
-package org.thoughtcrime.securesms.database;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.support.annotation.NonNull;
-import android.support.annotation.VisibleForTesting;
-import android.telephony.PhoneNumberUtils;
-import android.text.TextUtils;
-import android.util.Log;
-
-import org.thoughtcrime.securesms.util.GroupUtil;
-import org.thoughtcrime.securesms.util.LRUCache;
-import org.thoughtcrime.securesms.util.ShortCodeUtil;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
-import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class CanonicalAddressDatabase {
-
- private static final String TAG = CanonicalAddressDatabase.class.getSimpleName();
-
- private static final int DATABASE_VERSION = 1;
- private static final String DATABASE_NAME = "canonical_address.db";
- private static final String TABLE = "canonical_addresses";
- private static final String ID_COLUMN = "_id";
- private static final String ADDRESS_COLUMN = "address";
-
- private static final String DATABASE_CREATE = "CREATE TABLE " + TABLE + " (" + ID_COLUMN + " integer PRIMARY KEY, " + ADDRESS_COLUMN + " TEXT NOT NULL);";
- private static final String SELECTION_NUMBER = "PHONE_NUMBERS_EQUAL(" + ADDRESS_COLUMN + ", ?)";
- private static final String SELECTION_OTHER = ADDRESS_COLUMN + " = ? COLLATE NOCASE";
-
- private static CanonicalAddressDatabase instance;
- private DatabaseHelper databaseHelper;
- private final Context context;
-
- private final Map addressCache = new ConcurrentHashMap<>();
- private final Map idCache = new ConcurrentHashMap<>();
- private final Map formattedAddressCache = Collections.synchronizedMap(new LRUCache(100));
-
- public synchronized static CanonicalAddressDatabase getInstance(Context context) {
- if (instance == null)
- instance = new CanonicalAddressDatabase(context.getApplicationContext());
-
- return instance;
- }
-
- private CanonicalAddressDatabase(Context context) {
- this.context = context;
- this.databaseHelper = new DatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
-
- fillCache();
- }
-
- public void reset(Context context) {
- DatabaseHelper old = this.databaseHelper;
- this.databaseHelper = new DatabaseHelper(context.getApplicationContext(), DATABASE_NAME, null, DATABASE_VERSION);
- old.close();
- fillCache();
- }
-
- private void fillCache() {
- Cursor cursor = null;
-
- try {
- SQLiteDatabase db = databaseHelper.getReadableDatabase();
- cursor = db.query(TABLE, null, null, null, null, null, null);
-
- while (cursor != null && cursor.moveToNext()) {
- long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID_COLUMN));
- String address = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS_COLUMN));
-
- if (address == null || address.trim().length() == 0)
- address = "Anonymous";
-
- idCache.put(id, address);
- addressCache.put(address, id);
- }
- } finally {
- if (cursor != null)
- cursor.close();
- }
- }
-
- public @NonNull String getAddressFromId(long id) {
- String cachedAddress = idCache.get(id);
-
- if (cachedAddress != null)
- return cachedAddress;
-
- Cursor cursor = null;
-
- try {
- Log.w(TAG, "Hitting DB on query [ID].");
-
- SQLiteDatabase db = databaseHelper.getReadableDatabase();
- cursor = db.query(TABLE, null, ID_COLUMN + " = ?", new String[] {id+""}, null, null, null);
-
- if (!cursor.moveToFirst())
- return "Anonymous";
-
- String address = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS_COLUMN));
-
- if (address == null || address.trim().equals("")) {
- return "Anonymous";
- } else {
- idCache.put(id, address);
- return address;
- }
- } finally {
- if (cursor != null)
- cursor.close();
- }
- }
-
- public void close() {
- databaseHelper.close();
- instance = null;
- }
-
- public long getCanonicalAddressId(@NonNull String address) {
- try {
- long canonicalAddressId;
- String formattedAddress;
-
- if ((formattedAddress = formattedAddressCache.get(address)) == null) {
- String localNumber = TextSecurePreferences.getLocalNumber(context);
-
- if (!isNumberAddress(address) ||
- !TextSecurePreferences.isPushRegistered(context) ||
- ShortCodeUtil.isShortCode(localNumber, address))
- {
- formattedAddress = address;
- } else {
- formattedAddress = PhoneNumberFormatter.formatNumber(address, localNumber);
- }
-
- formattedAddressCache.put(address, formattedAddress);
- }
-
- if ((canonicalAddressId = getCanonicalAddressFromCache(formattedAddress)) == -1) {
- canonicalAddressId = getCanonicalAddressIdFromDatabase(formattedAddress);
- }
-
- idCache.put(canonicalAddressId, formattedAddress);
- addressCache.put(formattedAddress, canonicalAddressId);
-
- return canonicalAddressId;
- } catch (InvalidNumberException e) {
- throw new AssertionError(e);
- }
- }
-
- public @NonNull List getCanonicalAddressIds(@NonNull List addresses) {
- List addressList = new LinkedList<>();
-
- for (String address : addresses) {
- addressList.add(getCanonicalAddressId(address));
- }
-
- return addressList;
- }
-
- private long getCanonicalAddressFromCache(String address) {
- Long cachedAddress = addressCache.get(address);
- return cachedAddress == null ? -1L : cachedAddress;
- }
-
- private long getCanonicalAddressIdFromDatabase(@NonNull String address) {
- Log.w(TAG, "Hitting DB on query [ADDRESS]");
-
- Cursor cursor = null;
-
- try {
- SQLiteDatabase db = databaseHelper.getWritableDatabase();
- String[] selectionArguments = new String[]{address};
- boolean isNumber = isNumberAddress(address);
-
- cursor = db.query(TABLE, null, isNumber ? SELECTION_NUMBER : SELECTION_OTHER,
- selectionArguments, null, null, null);
-
- if (cursor.getCount() == 0 || !cursor.moveToFirst()) {
- ContentValues contentValues = new ContentValues(1);
- contentValues.put(ADDRESS_COLUMN, address);
- return db.insert(TABLE, ADDRESS_COLUMN, contentValues);
- } else {
- long canonicalId = cursor.getLong(cursor.getColumnIndexOrThrow(ID_COLUMN));
- String oldAddress = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS_COLUMN));
-
- if (!address.equals(oldAddress)) {
- ContentValues contentValues = new ContentValues(1);
- contentValues.put(ADDRESS_COLUMN, address);
- db.update(TABLE, contentValues, ID_COLUMN + " = ?", new String[]{canonicalId+""});
-
- addressCache.remove(oldAddress);
- }
-
- return canonicalId;
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
-
- @VisibleForTesting
- static boolean isNumberAddress(@NonNull String number) {
- if (number.contains("@")) return false;
- if (GroupUtil.isEncodedGroup(number)) return false;
-
- final String networkNumber = PhoneNumberUtils.extractNetworkPortion(number);
-
- if (TextUtils.isEmpty(networkNumber)) return false;
- if (networkNumber.length() < 3) return false;
-
- return PhoneNumberUtils.isWellFormedSmsAddress(number);
- }
-
- private static class DatabaseHelper extends SQLiteOpenHelper {
-
- public DatabaseHelper(Context context, String name, CursorFactory factory, int version) {
- super(context, name, factory, version);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL(DATABASE_CREATE);
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- }
-
- }
-}
diff --git a/src/org/thoughtcrime/securesms/database/CanonicalSessionMigrator.java b/src/org/thoughtcrime/securesms/database/CanonicalSessionMigrator.java
deleted file mode 100644
index 587ca26546..0000000000
--- a/src/org/thoughtcrime/securesms/database/CanonicalSessionMigrator.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Copyright (C) 2011 Whisper Systems
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.thoughtcrime.securesms.database;
-
-import android.content.Context;
-import android.util.Log;
-
-import java.io.File;
-
-public class CanonicalSessionMigrator {
-
- private static void migrateSession(File sessionFile, File sessionsDirectory, long canonicalAddress) {
- File canonicalSessionFile = new File(sessionsDirectory.getAbsolutePath() + File.separatorChar + canonicalAddress);
- sessionFile.renameTo(canonicalSessionFile);
- Log.w("CanonicalSessionMigrator", "Moving: " + sessionFile.toString() + " to " + canonicalSessionFile.toString());
-
- File canonicalSessionFileLocal = new File(sessionsDirectory.getAbsolutePath() + File.separatorChar + canonicalAddress + "-local");
- File localFile = new File(sessionFile.getAbsolutePath() + "-local");
- if (localFile.exists())
- localFile.renameTo(canonicalSessionFileLocal);
-
- Log.w("CanonicalSessionMigrator", "Moving " + localFile + " to " + canonicalSessionFileLocal);
-
- File canonicalSessionFileRemote = new File(sessionsDirectory.getAbsolutePath() + File.separatorChar + canonicalAddress + "-remote");
- File remoteFile = new File(sessionFile.getAbsolutePath() + "-remote");
- if (remoteFile.exists())
- remoteFile.renameTo(canonicalSessionFileRemote);
-
- Log.w("CanonicalSessionMigrator", "Moving " + remoteFile + " to " + canonicalSessionFileRemote);
-
- }
-
- public static void migrateSessions(Context context) {
- if (context.getSharedPreferences("SecureSMS", Context.MODE_PRIVATE).getBoolean("canonicalized", false))
- return;
-
- CanonicalAddressDatabase canonicalDb = CanonicalAddressDatabase.getInstance(context);
- File rootDirectory = context.getFilesDir();
- File sessionsDirectory = new File(rootDirectory.getAbsolutePath() + File.separatorChar + "sessions");
- sessionsDirectory.mkdir();
-
- String[] files = rootDirectory.list();
-
- for (int i=0;i newDocumentList = new LinkedList<>();
+
+ for (PreCanonicalAddressIdentityMismatchDocument oldDocument : oldDocumentList.list) {
+ Cursor resolved = canonicalAddressDatabase.query("canonical_addresses", new String[] {"address"}, "_id = ?", new String[] {String.valueOf(oldDocument.recipientId)}, null, null, null);
+
+ if (resolved != null && resolved.moveToFirst()) {
+ String address = resolved.getString(0);
+ newDocumentList.add(new PostCanonicalAddressIdentityMismatchDocument(numberMigrator.migrate(address), oldDocument.identityKey));
+ } else {
+ throw new AssertionError("Unable to resolve: " + oldDocument.recipientId);
+ }
+
+ if (resolved != null) resolved.close();
+ }
+
+ ContentValues values = new ContentValues(1);
+ values.put("mismatched_identities", JsonUtils.toJson(new PostCanonicalAddressIdentityMismatchList(newDocumentList)));
+ db.update("sms", values, "_id = ?", new String[] {String.valueOf(id)});
+ } catch (IOException e) {
+ Log.w(TAG, e);
+ }
+ }
+ }
+
+ if (cursor != null) cursor.close();
+
+ // Migrate MMS mismatched identities
+ cursor = db.query("mms", new String[] {"_id", "mismatched_identities"}, "mismatched_identities IS NOT NULL", null, null, null, null);
+
+ while (cursor != null && cursor.moveToNext()) {
+ long id = cursor.getLong(0);
+ String document = cursor.getString(1);
+
+ if (!TextUtils.isEmpty(document)) {
+ try {
+ PreCanonicalAddressIdentityMismatchList oldDocumentList = JsonUtils.fromJson(document, PreCanonicalAddressIdentityMismatchList.class);
+ List newDocumentList = new LinkedList<>();
+
+ for (PreCanonicalAddressIdentityMismatchDocument oldDocument : oldDocumentList.list) {
+ Cursor resolved = canonicalAddressDatabase.query("canonical_addresses", new String[] {"address"}, "_id = ?", new String[] {String.valueOf(oldDocument.recipientId)}, null, null, null);
+
+ if (resolved != null && resolved.moveToFirst()) {
+ String address = resolved.getString(0);
+ newDocumentList.add(new PostCanonicalAddressIdentityMismatchDocument(numberMigrator.migrate(address), oldDocument.identityKey));
+ } else {
+ throw new AssertionError("Unable to resolve: " + oldDocument.recipientId);
+ }
+
+ if (resolved != null) resolved.close();
+ }
+
+ ContentValues values = new ContentValues(1);
+ values.put("mismatched_identities", JsonUtils.toJson(new PostCanonicalAddressIdentityMismatchList(newDocumentList)));
+ db.update("mms", values, "_id = ?", new String[] {String.valueOf(id)});
+ } catch (IOException e) {
+ Log.w(TAG, e);
+ }
+ }
+ }
+
+ if (cursor != null) cursor.close();
+
+ // Migrate MMS network failures
+ cursor = db.query("mms", new String[] {"_id", "network_failures"}, "network_failures IS NOT NULL", null, null, null, null);
+
+ while (cursor != null && cursor.moveToNext()) {
+ long id = cursor.getLong(0);
+ String document = cursor.getString(1);
+
+ if (!TextUtils.isEmpty(document)) {
+ try {
+ PreCanonicalAddressNetworkFailureList oldDocumentList = JsonUtils.fromJson(document, PreCanonicalAddressNetworkFailureList.class);
+ List newDocumentList = new LinkedList<>();
+
+ for (PreCanonicalAddressNetworkFailureDocument oldDocument : oldDocumentList.list) {
+ Cursor resolved = canonicalAddressDatabase.query("canonical_addresses", new String[] {"address"}, "_id = ?", new String[] {String.valueOf(oldDocument.recipientId)}, null, null, null);
+
+ if (resolved != null && resolved.moveToFirst()) {
+ String address = resolved.getString(0);
+ newDocumentList.add(new PostCanonicalAddressNetworkFailureDocument(numberMigrator.migrate(address)));
+ } else {
+ throw new AssertionError("Unable to resolve: " + oldDocument.recipientId);
+ }
+
+ if (resolved != null) resolved.close();
+ }
+
+ ContentValues values = new ContentValues(1);
+ values.put("network_failures", JsonUtils.toJson(new PostCanonicalAddressNetworkFailureList(newDocumentList)));
+ db.update("mms", values, "_id = ?", new String[] {String.valueOf(id)});
+ } catch (IOException e) {
+ Log.w(TAG, e);
+ }
+ }
+ }
+
+ // Migrate sessions
+ File sessionsDirectory = new File(context.getFilesDir(), "sessions-v2");
+
+ if (sessionsDirectory.exists() && sessionsDirectory.isDirectory()) {
+ File[] sessions = sessionsDirectory.listFiles();
+
+ for (File session : sessions) {
+ try {
+ String[] sessionParts = session.getName().split("[.]");
+ long recipientId = Long.parseLong(sessionParts[0]);
+
+ int deviceId;
+
+ if (sessionParts.length > 1) deviceId = Integer.parseInt(sessionParts[1]);
+ else deviceId = 1;
+
+ Cursor resolved = canonicalAddressDatabase.query("canonical_addresses", new String[] {"address"}, "_id = ?", new String[] {String.valueOf(recipientId)}, null, null, null);
+
+ if (resolved != null && resolved.moveToNext()) {
+ String address = resolved.getString(0);
+ File destination = new File(session.getParentFile(), address + (deviceId != 1 ? "." + deviceId : ""));
+
+ if (!session.renameTo(destination)) {
+ Log.w(TAG, "Session rename failed: " + destination);
+ }
+ }
+
+ if (resolved != null) resolved.close();
+ } catch (NumberFormatException e) {
+ Log.w(TAG, e);
+ }
+ }
+ }
+
+ }
+
db.setTransactionSuccessful();
db.endTransaction();
}
@@ -893,4 +1202,153 @@ public class DatabaseFactory {
}
}
+
+ private static class PreCanonicalAddressIdentityMismatchList {
+ @JsonProperty(value = "m")
+ private List list;
+ }
+
+ private static class PostCanonicalAddressIdentityMismatchList {
+ @JsonProperty(value = "m")
+ private List list;
+
+ public PostCanonicalAddressIdentityMismatchList(List list) {
+ this.list = list;
+ }
+ }
+
+ private static class PreCanonicalAddressIdentityMismatchDocument {
+ @JsonProperty(value = "r")
+ private long recipientId;
+
+ @JsonProperty(value = "k")
+ private String identityKey;
+ }
+
+ private static class PostCanonicalAddressIdentityMismatchDocument {
+ @JsonProperty(value = "a")
+ private String address;
+
+ @JsonProperty(value = "k")
+ private String identityKey;
+
+ public PostCanonicalAddressIdentityMismatchDocument() {}
+
+ public PostCanonicalAddressIdentityMismatchDocument(String address, String identityKey) {
+ this.address = address;
+ this.identityKey = identityKey;
+ }
+ }
+
+ private static class PreCanonicalAddressNetworkFailureList {
+ @JsonProperty(value = "l")
+ private List list;
+ }
+
+ private static class PostCanonicalAddressNetworkFailureList {
+ @JsonProperty(value = "l")
+ private List list;
+
+ public PostCanonicalAddressNetworkFailureList(List list) {
+ this.list = list;
+ }
+ }
+
+ private static class PreCanonicalAddressNetworkFailureDocument {
+ @JsonProperty(value = "r")
+ private long recipientId;
+ }
+
+ private static class PostCanonicalAddressNetworkFailureDocument {
+ @JsonProperty(value = "a")
+ private String address;
+
+ public PostCanonicalAddressNetworkFailureDocument() {}
+
+ public PostCanonicalAddressNetworkFailureDocument(String address) {
+ this.address = address;
+ }
+ }
+
+ private static class NumberMigrator {
+
+ private static final String TAG = NumberMigrator.class.getSimpleName();
+
+ private static final Set SHORT_COUNTRIES = new HashSet() {{
+ add("NU");
+ add("TK");
+ add("NC");
+ add("AC");
+ }};
+
+ private final Phonenumber.PhoneNumber localNumber;
+ private final String localNumberString;
+ private final String localCountryCode;
+
+ private final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+
+ public NumberMigrator(String localNumber) {
+ try {
+ this.localNumberString = localNumber;
+ this.localNumber = phoneNumberUtil.parse(localNumber, null);
+ this.localCountryCode = phoneNumberUtil.getRegionCodeForNumber(this.localNumber);
+ } catch (NumberParseException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public String migrate(@Nullable String number) {
+ if (number == null) return "Unknown";
+ if (number.startsWith("__textsecure_group__!")) return number;
+ if (android.util.Patterns.EMAIL_ADDRESS.matcher(number).matches()) return number;
+
+ String bareNumber = number.replaceAll("[^0-9+]", "");
+
+ if (bareNumber.length() == 0) {
+ if (TextUtils.isEmpty(number.trim())) return "Unknown";
+ else return number.trim();
+ }
+
+ // libphonenumber doesn't seem to be correct for Germany and Finland
+ if (bareNumber.length() <= 6 && ("DE".equals(localCountryCode) || "FI".equals(localCountryCode) || "SK".equals(localCountryCode))) {
+ return bareNumber;
+ }
+
+ // libphonenumber seems incorrect for Russia and a few other countries with 4 digit short codes.
+ if (bareNumber.length() <= 4 && !SHORT_COUNTRIES.contains(localCountryCode)) {
+ return bareNumber;
+ }
+
+ try {
+ Phonenumber.PhoneNumber parsedNumber = phoneNumberUtil.parse(bareNumber, localCountryCode);
+
+ if (ShortNumberInfo.getInstance().isPossibleShortNumberForRegion(parsedNumber, localCountryCode)) {
+ return bareNumber;
+ }
+
+ return phoneNumberUtil.format(parsedNumber, PhoneNumberUtil.PhoneNumberFormat.E164);
+ } catch (NumberParseException e) {
+ Log.w(TAG, e);
+ if (bareNumber.charAt(0) == '+')
+ return bareNumber;
+
+ String localNumberImprecise = localNumberString;
+
+ if (localNumberImprecise.charAt(0) == '+')
+ localNumberImprecise = localNumberImprecise.substring(1);
+
+ if (localNumberImprecise.length() == number.length() || number.length() > localNumberImprecise.length())
+ return "+" + number;
+
+ int difference = localNumberImprecise.length() - number.length();
+
+ return "+" + localNumberImprecise.substring(0, difference) + number;
+ }
+ }
+
+
+
+ }
+
+
}
diff --git a/src/org/thoughtcrime/securesms/database/EarlyReceiptCache.java b/src/org/thoughtcrime/securesms/database/EarlyReceiptCache.java
index b23301e0ca..f1648397a2 100644
--- a/src/org/thoughtcrime/securesms/database/EarlyReceiptCache.java
+++ b/src/org/thoughtcrime/securesms/database/EarlyReceiptCache.java
@@ -11,7 +11,7 @@ public class EarlyReceiptCache {
private final LRUCache cache = new LRUCache<>(100);
- public synchronized void increment(long timestamp, String address) {
+ public synchronized void increment(long timestamp, Address address) {
Log.w(TAG, this+"");
Log.w(TAG, String.format("Early receipt: %d,%s", timestamp, address));
Placeholder tuple = new Placeholder(timestamp, address);
@@ -24,7 +24,7 @@ public class EarlyReceiptCache {
}
}
- public synchronized long remove(long timestamp, String address) {
+ public synchronized long remove(long timestamp, Address address) {
Long count = cache.remove(new Placeholder(timestamp, address));
Log.w(TAG, this+"");
Log.w(TAG, String.format("Checking early receipts (%d, %s): %d", timestamp, address, count));
@@ -34,9 +34,9 @@ public class EarlyReceiptCache {
private class Placeholder {
private final long timestamp;
- private final @NonNull String address;
+ private final @NonNull Address address;
- private Placeholder(long timestamp, @NonNull String address) {
+ private Placeholder(long timestamp, @NonNull Address address) {
this.timestamp = timestamp;
this.address = address;
}
diff --git a/src/org/thoughtcrime/securesms/database/GroupDatabase.java b/src/org/thoughtcrime/securesms/database/GroupDatabase.java
index b64ce90c4e..bad4ccdbc4 100644
--- a/src/org/thoughtcrime/securesms/database/GroupDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/GroupDatabase.java
@@ -101,22 +101,20 @@ public class GroupDatabase extends Database {
}
public @NonNull Recipients getGroupMembers(byte[] groupId, boolean includeSelf) {
- String localNumber = TextSecurePreferences.getLocalNumber(context);
- List members = getCurrentMembers(groupId);
+ List members = getCurrentMembers(groupId);
List recipients = new LinkedList<>();
- for (String member : members) {
- if (!includeSelf && member.equals(localNumber))
+ for (Address member : members) {
+ if (!includeSelf && Util.isOwnNumber(context, member))
continue;
- recipients.addAll(RecipientFactory.getRecipientsFromString(context, member, false)
- .getRecipientsList());
+ recipients.add(RecipientFactory.getRecipientFor(context, member, false));
}
return RecipientFactory.getRecipientsFor(context, recipients, false);
}
- public void create(byte[] groupId, String title, List members,
+ public void create(byte[] groupId, String title, List members,
SignalServiceAttachmentPointer avatar, String relay)
{
ContentValues contentValues = new ContentValues();
@@ -185,7 +183,7 @@ public class GroupDatabase extends Database {
notifyDatabaseListeners();
}
- public void updateMembers(byte[] id, List members) {
+ public void updateMembers(byte[] id, List members) {
ContentValues contents = new ContentValues();
contents.put(MEMBERS, Util.join(members, ","));
contents.put(ACTIVE, 1);
@@ -194,8 +192,8 @@ public class GroupDatabase extends Database {
new String[] {GroupUtil.getEncodedId(id)});
}
- public void remove(byte[] id, String source) {
- List currentMembers = getCurrentMembers(id);
+ public void remove(byte[] id, Address source) {
+ List currentMembers = getCurrentMembers(id);
currentMembers.remove(source);
ContentValues contents = new ContentValues();
@@ -205,7 +203,7 @@ public class GroupDatabase extends Database {
new String[] {GroupUtil.getEncodedId(id)});
}
- private List getCurrentMembers(byte[] id) {
+ private List getCurrentMembers(byte[] id) {
Cursor cursor = null;
try {
@@ -215,7 +213,13 @@ public class GroupDatabase extends Database {
null, null, null);
if (cursor != null && cursor.moveToFirst()) {
- return Util.split(cursor.getString(cursor.getColumnIndexOrThrow(MEMBERS)), ",");
+ List results = new LinkedList<>();
+
+ for (String member : Util.split(cursor.getString(cursor.getColumnIndexOrThrow(MEMBERS)), ",")) {
+ results.add(Address.fromSerialized(member));
+ }
+
+ return results;
}
return new LinkedList<>();
@@ -286,16 +290,16 @@ public class GroupDatabase extends Database {
public static class GroupRecord {
- private final String id;
- private final String title;
- private final List members;
- private final byte[] avatar;
- private final long avatarId;
- private final byte[] avatarKey;
- private final byte[] avatarDigest;
- private final String avatarContentType;
- private final String relay;
- private final boolean active;
+ private final String id;
+ private final String title;
+ private final List members;
+ private final byte[] avatar;
+ private final long avatarId;
+ private final byte[] avatarKey;
+ private final byte[] avatarDigest;
+ private final String avatarContentType;
+ private final String relay;
+ private final boolean active;
public GroupRecord(String id, String title, String members, byte[] avatar,
long avatarId, byte[] avatarKey, String avatarContentType,
@@ -303,7 +307,7 @@ public class GroupDatabase extends Database {
{
this.id = id;
this.title = title;
- this.members = Util.split(members, ",");
+ this.members = Address.fromSerializedList(members, ",");
this.avatar = avatar;
this.avatarId = avatarId;
this.avatarKey = avatarKey;
@@ -329,7 +333,7 @@ public class GroupDatabase extends Database {
return title;
}
- public List getMembers() {
+ public List getMembers() {
return members;
}
diff --git a/src/org/thoughtcrime/securesms/database/IdentityDatabase.java b/src/org/thoughtcrime/securesms/database/IdentityDatabase.java
index 13b2293aa9..715fb14fdd 100644
--- a/src/org/thoughtcrime/securesms/database/IdentityDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/IdentityDatabase.java
@@ -38,7 +38,7 @@ public class IdentityDatabase extends Database {
private static final String TABLE_NAME = "identities";
private static final String ID = "_id";
- private static final String RECIPIENT = "recipient";
+ private static final String ADDRESS = "address";
private static final String IDENTITY_KEY = "key";
private static final String TIMESTAMP = "timestamp";
private static final String FIRST_USE = "first_use";
@@ -47,7 +47,7 @@ public class IdentityDatabase extends Database {
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME +
" (" + ID + " INTEGER PRIMARY KEY, " +
- RECIPIENT + " INTEGER UNIQUE, " +
+ ADDRESS + " TEXT UNIQUE, " +
IDENTITY_KEY + " TEXT, " +
FIRST_USE + " INTEGER DEFAULT 0, " +
TIMESTAMP + " INTEGER DEFAULT 0, " +
@@ -65,8 +65,8 @@ public class IdentityDatabase extends Database {
}
public static VerifiedStatus forState(int state) {
- if (state == 0) return DEFAULT;
- else if (state == 1) return VERIFIED;
+ if (state == 0) return DEFAULT;
+ else if (state == 1) return VERIFIED;
else if (state == 2) return UNVERIFIED;
else throw new AssertionError("No such state: " + state);
}
@@ -86,13 +86,13 @@ public class IdentityDatabase extends Database {
return new IdentityReader(cursor);
}
- public Optional getIdentity(long recipientId) {
+ public Optional getIdentity(Address address) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = null;
try {
- cursor = database.query(TABLE_NAME, null, RECIPIENT + " = ?",
- new String[] {recipientId + ""}, null, null, null);
+ cursor = database.query(TABLE_NAME, null, ADDRESS + " = ?",
+ new String[] {address.serialize()}, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
return Optional.of(getIdentityRecord(cursor));
@@ -106,14 +106,14 @@ public class IdentityDatabase extends Database {
return Optional.absent();
}
- public void saveIdentity(long recipientId, IdentityKey identityKey, VerifiedStatus verifiedStatus,
+ public void saveIdentity(Address address, IdentityKey identityKey, VerifiedStatus verifiedStatus,
boolean firstUse, long timestamp, boolean nonBlockingApproval)
{
SQLiteDatabase database = databaseHelper.getWritableDatabase();
String identityKeyString = Base64.encodeBytes(identityKey.serialize());
ContentValues contentValues = new ContentValues();
- contentValues.put(RECIPIENT, recipientId);
+ contentValues.put(ADDRESS, address.serialize());
contentValues.put(IDENTITY_KEY, identityKeyString);
contentValues.put(TIMESTAMP, timestamp);
contentValues.put(VERIFIED, verifiedStatus.toInt());
@@ -122,38 +122,36 @@ public class IdentityDatabase extends Database {
database.replace(TABLE_NAME, null, contentValues);
- EventBus.getDefault().post(new IdentityRecord(recipientId, identityKey, verifiedStatus,
+ EventBus.getDefault().post(new IdentityRecord(address, identityKey, verifiedStatus,
firstUse, timestamp, nonBlockingApproval));
}
- public void setApproval(long recipientId, boolean nonBlockingApproval) {
+ public void setApproval(Address address, boolean nonBlockingApproval) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues(2);
contentValues.put(NONBLOCKING_APPROVAL, nonBlockingApproval);
- database.update(TABLE_NAME, contentValues, RECIPIENT + " = ?",
- new String[] {String.valueOf(recipientId)});
+ database.update(TABLE_NAME, contentValues, ADDRESS + " = ?", new String[] {address.serialize()});
}
- public void setVerified(long recipientId, IdentityKey identityKey, VerifiedStatus verifiedStatus) {
+ public void setVerified(Address address, IdentityKey identityKey, VerifiedStatus verifiedStatus) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues(1);
contentValues.put(VERIFIED, verifiedStatus.toInt());
- int updated = database.update(TABLE_NAME, contentValues, RECIPIENT + " = ? AND " + IDENTITY_KEY + " = ?",
- new String[] {String.valueOf(recipientId),
- Base64.encodeBytes(identityKey.serialize())});
+ int updated = database.update(TABLE_NAME, contentValues, ADDRESS + " = ? AND " + IDENTITY_KEY + " = ?",
+ new String[] {address.serialize(), Base64.encodeBytes(identityKey.serialize())});
if (updated > 0) {
- Optional record = getIdentity(recipientId);
+ Optional record = getIdentity(address);
if (record.isPresent()) EventBus.getDefault().post(record.get());
}
}
private IdentityRecord getIdentityRecord(@NonNull Cursor cursor) throws IOException, InvalidKeyException {
- long recipientId = cursor.getLong(cursor.getColumnIndexOrThrow(RECIPIENT));
+ String address = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS));
String serializedIdentity = cursor.getString(cursor.getColumnIndexOrThrow(IDENTITY_KEY));
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP));
int verifiedStatus = cursor.getInt(cursor.getColumnIndexOrThrow(VERIFIED));
@@ -161,23 +159,23 @@ public class IdentityDatabase extends Database {
boolean firstUse = cursor.getInt(cursor.getColumnIndexOrThrow(FIRST_USE)) == 1;
IdentityKey identity = new IdentityKey(Base64.decode(serializedIdentity), 0);
- return new IdentityRecord(recipientId, identity, VerifiedStatus.forState(verifiedStatus), firstUse, timestamp, nonblockingApproval);
+ return new IdentityRecord(Address.fromSerialized(address), identity, VerifiedStatus.forState(verifiedStatus), firstUse, timestamp, nonblockingApproval);
}
public static class IdentityRecord {
- private final long recipientId;
+ private final Address address;
private final IdentityKey identitykey;
private final VerifiedStatus verifiedStatus;
private final boolean firstUse;
private final long timestamp;
private final boolean nonblockingApproval;
- private IdentityRecord(long recipientId,
+ private IdentityRecord(Address address,
IdentityKey identitykey, VerifiedStatus verifiedStatus,
boolean firstUse, long timestamp, boolean nonblockingApproval)
{
- this.recipientId = recipientId;
+ this.address = address;
this.identitykey = identitykey;
this.verifiedStatus = verifiedStatus;
this.firstUse = firstUse;
@@ -185,8 +183,8 @@ public class IdentityDatabase extends Database {
this.nonblockingApproval = nonblockingApproval;
}
- public long getRecipientId() {
- return recipientId;
+ public Address getAddress() {
+ return address;
}
public IdentityKey getIdentityKey() {
@@ -211,7 +209,7 @@ public class IdentityDatabase extends Database {
@Override
public String toString() {
- return "{recipientId: " + recipientId + ", identityKey: " + identitykey + ", verifiedStatus: " + verifiedStatus + ", firstUse: " + firstUse + "}";
+ return "{address: " + address + ", identityKey: " + identitykey + ", verifiedStatus: " + verifiedStatus + ", firstUse: " + firstUse + "}";
}
}
diff --git a/src/org/thoughtcrime/securesms/database/MediaDatabase.java b/src/org/thoughtcrime/securesms/database/MediaDatabase.java
index cdc56342fd..4a5e0181b8 100644
--- a/src/org/thoughtcrime/securesms/database/MediaDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/MediaDatabase.java
@@ -5,9 +5,9 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.attachments.Attachment;
-import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
@@ -57,10 +57,10 @@ public class MediaDatabase extends Database {
public static class MediaRecord {
private final DatabaseAttachment attachment;
- private final String address;
+ private final Address address;
private final long date;
- private MediaRecord(DatabaseAttachment attachment, String address, long date) {
+ private MediaRecord(DatabaseAttachment attachment, @Nullable Address address, long date) {
this.attachment = attachment;
this.address = address;
this.date = date;
@@ -69,7 +69,12 @@ public class MediaDatabase extends Database {
public static MediaRecord from(@NonNull Context context, @NonNull MasterSecret masterSecret, @NonNull Cursor cursor) {
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
DatabaseAttachment attachment = attachmentDatabase.getAttachment(masterSecret, cursor);
- String address = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS));
+ String serializedAddress = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS));
+ Address address = null;
+
+ if (serializedAddress != null) {
+ address = Address.fromSerialized(serializedAddress);
+ }
long date;
@@ -90,7 +95,7 @@ public class MediaDatabase extends Database {
return attachment.getContentType();
}
- public String getAddress() {
+ public @Nullable Address getAddress() {
return address;
}
diff --git a/src/org/thoughtcrime/securesms/database/MessagingDatabase.java b/src/org/thoughtcrime/securesms/database/MessagingDatabase.java
index 6a660aa604..775a7c2339 100644
--- a/src/org/thoughtcrime/securesms/database/MessagingDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/MessagingDatabase.java
@@ -17,7 +17,6 @@ import org.whispersystems.libsignal.IdentityKey;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
public abstract class MessagingDatabase extends Database implements MmsSmsColumns {
@@ -30,9 +29,9 @@ public abstract class MessagingDatabase extends Database implements MmsSmsColumn
protected abstract String getTableName();
- public void setMismatchedIdentity(long messageId, final long recipientId, final IdentityKey identityKey) {
+ public void setMismatchedIdentity(long messageId, final Address address, final IdentityKey identityKey) {
List items = new ArrayList() {{
- add(new IdentityKeyMismatch(recipientId, identityKey));
+ add(new IdentityKeyMismatch(address, identityKey));
}};
IdentityKeyMismatchList document = new IdentityKeyMismatchList(items);
@@ -51,20 +50,20 @@ public abstract class MessagingDatabase extends Database implements MmsSmsColumn
}
}
- public void addMismatchedIdentity(long messageId, long recipientId, IdentityKey identityKey) {
+ public void addMismatchedIdentity(long messageId, Address address, IdentityKey identityKey) {
try {
addToDocument(messageId, MISMATCHED_IDENTITIES,
- new IdentityKeyMismatch(recipientId, identityKey),
+ new IdentityKeyMismatch(address, identityKey),
IdentityKeyMismatchList.class);
} catch (IOException e) {
Log.w(TAG, e);
}
}
- public void removeMismatchedIdentity(long messageId, long recipientId, IdentityKey identityKey) {
+ public void removeMismatchedIdentity(long messageId, Address address, IdentityKey identityKey) {
try {
removeFromDocument(messageId, MISMATCHED_IDENTITIES,
- new IdentityKeyMismatch(recipientId, identityKey),
+ new IdentityKeyMismatch(address, identityKey),
IdentityKeyMismatchList.class);
} catch (IOException e) {
Log.w(TAG, e);
@@ -168,15 +167,15 @@ public abstract class MessagingDatabase extends Database implements MmsSmsColumn
public static class SyncMessageId {
- private final String address;
+ private final Address address;
private final long timetamp;
- public SyncMessageId(String address, long timetamp) {
+ public SyncMessageId(Address address, long timetamp) {
this.address = address;
this.timetamp = timetamp;
}
- public String getAddress() {
+ public Address getAddress() {
return address;
}
diff --git a/src/org/thoughtcrime/securesms/database/MmsAddressDatabase.java b/src/org/thoughtcrime/securesms/database/MmsAddressDatabase.java
index 6753799d9b..d31deed4dd 100644
--- a/src/org/thoughtcrime/securesms/database/MmsAddressDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/MmsAddressDatabase.java
@@ -55,18 +55,18 @@ public class MmsAddressDatabase extends Database {
super(context, databaseHelper);
}
- private void insertAddress(long messageId, int type, @NonNull String value) {
+ private void insertAddress(long messageId, int type, @NonNull Address value) {
SQLiteDatabase database = databaseHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(MMS_ID, messageId);
contentValues.put(TYPE, type);
- contentValues.put(ADDRESS, value);
+ contentValues.put(ADDRESS, value.serialize());
contentValues.put(ADDRESS_CHARSET, "UTF-8");
database.insert(TABLE_NAME, null, contentValues);
}
- private void insertAddress(long messageId, int type, @NonNull List addresses) {
- for (String address : addresses) {
+ private void insertAddress(long messageId, int type, @NonNull List addresses) {
+ for (Address address : addresses) {
insertAddress(messageId, type, address);
}
}
@@ -84,17 +84,17 @@ public class MmsAddressDatabase extends Database {
public MmsAddresses getAddressesForId(long messageId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = null;
- String from = null;
- List to = new LinkedList<>();
- List cc = new LinkedList<>();
- List bcc = new LinkedList<>();
+ Address from = null;
+ List to = new LinkedList<>();
+ List cc = new LinkedList<>();
+ List bcc = new LinkedList<>();
try {
cursor = database.query(TABLE_NAME, null, MMS_ID + " = ?", new String[] {messageId+""}, null, null, null);
while (cursor != null && cursor.moveToNext()) {
- long type = cursor.getLong(cursor.getColumnIndexOrThrow(TYPE));
- String address = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS));
+ long type = cursor.getLong(cursor.getColumnIndexOrThrow(TYPE));
+ Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
if (type == PduHeaders.FROM) from = address;
if (type == PduHeaders.TO) to.add(address);
@@ -109,8 +109,8 @@ public class MmsAddressDatabase extends Database {
return new MmsAddresses(from, to, cc, bcc);
}
- public List getAddressesListForId(long messageId) {
- List results = new LinkedList<>();
+ public List getAddressesListForId(long messageId) {
+ List results = new LinkedList<>();
MmsAddresses addresses = getAddressesForId(messageId);
if (addresses.getFrom() != null) {
@@ -125,13 +125,12 @@ public class MmsAddressDatabase extends Database {
}
public Recipients getRecipientsForId(long messageId) {
- List numbers = getAddressesListForId(messageId);
- List results = new LinkedList<>();
+ List addresses = getAddressesListForId(messageId);
+ List results = new LinkedList<>();
- for (String number : numbers) {
- if (!PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.equals(number)) {
- results.add(RecipientFactory.getRecipientsFromString(context, number, false)
- .getPrimaryRecipient());
+ for (Address address : addresses) {
+ if (!PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.equals(address.serialize())) {
+ results.add(RecipientFactory.getRecipientFor(context, address, false));
}
}
diff --git a/src/org/thoughtcrime/securesms/database/MmsAddresses.java b/src/org/thoughtcrime/securesms/database/MmsAddresses.java
index 5913ae978a..21302a222b 100644
--- a/src/org/thoughtcrime/securesms/database/MmsAddresses.java
+++ b/src/org/thoughtcrime/securesms/database/MmsAddresses.java
@@ -8,13 +8,13 @@ import java.util.List;
public class MmsAddresses {
- private final @Nullable String from;
- private final @NonNull List to;
- private final @NonNull List cc;
- private final @NonNull List bcc;
+ private final @Nullable Address from;
+ private final @NonNull List to;
+ private final @NonNull List cc;
+ private final @NonNull List bcc;
- public MmsAddresses(@Nullable String from, @NonNull List to,
- @NonNull List cc, @NonNull List bcc)
+ public MmsAddresses(@Nullable Address from, @NonNull List to,
+ @NonNull List cc, @NonNull List bcc)
{
this.from = from;
this.to = to;
@@ -23,34 +23,34 @@ public class MmsAddresses {
}
@NonNull
- public List getTo() {
+ public List getTo() {
return to;
}
@NonNull
- public List getCc() {
+ public List getCc() {
return cc;
}
@NonNull
- public List getBcc() {
+ public List getBcc() {
return bcc;
}
@Nullable
- public String getFrom() {
+ public Address getFrom() {
return from;
}
- public static MmsAddresses forTo(@NonNull List to) {
- return new MmsAddresses(null, to, new LinkedList(), new LinkedList());
+ public static MmsAddresses forTo(@NonNull List to) {
+ return new MmsAddresses(null, to, new LinkedList(), new LinkedList());
}
- public static MmsAddresses forBcc(@NonNull List bcc) {
- return new MmsAddresses(null, new LinkedList(), new LinkedList(), bcc);
+ public static MmsAddresses forBcc(@NonNull List bcc) {
+ return new MmsAddresses(null, new LinkedList(), new LinkedList(), bcc);
}
- public static MmsAddresses forFrom(@NonNull String from) {
- return new MmsAddresses(from, new LinkedList(), new LinkedList(), new LinkedList());
+ public static MmsAddresses forFrom(@NonNull Address from) {
+ return new MmsAddresses(from, new LinkedList(), new LinkedList(), new LinkedList());
}
}
diff --git a/src/org/thoughtcrime/securesms/database/MmsDatabase.java b/src/org/thoughtcrime/securesms/database/MmsDatabase.java
index 302d8c43a9..90889b2986 100644
--- a/src/org/thoughtcrime/securesms/database/MmsDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/MmsDatabase.java
@@ -51,16 +51,15 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord;
import org.thoughtcrime.securesms.jobs.TrimThreadJob;
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
+import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
import org.thoughtcrime.securesms.mms.SlideDeck;
-import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
import org.thoughtcrime.securesms.recipients.Recipients;
-import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.JsonUtils;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -68,7 +67,6 @@ import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobManager;
import org.whispersystems.libsignal.InvalidMessageException;
import org.whispersystems.libsignal.util.guava.Optional;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
@@ -78,11 +76,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
-import org.thoughtcrime.securesms.mms.MmsException;
-
-import static org.thoughtcrime.securesms.util.Util.canonicalizeNumber;
-import static org.thoughtcrime.securesms.util.Util.canonicalizeNumberOrGroup;
-
public class MmsDatabase extends MessagingDatabase {
private static final String TAG = MmsDatabase.class.getSimpleName();
@@ -212,39 +205,30 @@ public class MmsDatabase extends MessagingDatabase {
while (cursor.moveToNext()) {
if (Types.isOutgoingMessageType(cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX)))) {
- List addresses = addressDatabase.getAddressesListForId(cursor.getLong(cursor.getColumnIndexOrThrow(ID)));
+ List addresses = addressDatabase.getAddressesListForId(cursor.getLong(cursor.getColumnIndexOrThrow(ID)));
- for (String storedAddress : addresses) {
- try {
- String ourAddress = canonicalizeNumber(context, messageId.getAddress());
- String theirAddress = canonicalizeNumberOrGroup(context, storedAddress);
+ for (Address theirAddress : addresses) {
+ Address ourAddress = messageId.getAddress();
- if (ourAddress.equals(theirAddress) || GroupUtil.isEncodedGroup(theirAddress)) {
- long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
- long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
+ if (ourAddress.equals(theirAddress) || theirAddress.isGroup()) {
+ long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
+ long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
- found = true;
+ found = true;
- database.execSQL("UPDATE " + TABLE_NAME + " SET " +
- RECEIPT_COUNT + " = " + RECEIPT_COUNT + " + 1 WHERE " + ID + " = ?",
- new String[] {String.valueOf(id)});
+ database.execSQL("UPDATE " + TABLE_NAME + " SET " +
+ RECEIPT_COUNT + " = " + RECEIPT_COUNT + " + 1 WHERE " + ID + " = ?",
+ new String[] {String.valueOf(id)});
- DatabaseFactory.getThreadDatabase(context).update(threadId, false);
- notifyConversationListeners(threadId);
- }
- } catch (InvalidNumberException e) {
- Log.w("MmsDatabase", e);
+ DatabaseFactory.getThreadDatabase(context).update(threadId, false);
+ notifyConversationListeners(threadId);
}
}
}
}
if (!found) {
- try {
- earlyReceiptCache.increment(messageId.getTimetamp(), canonicalizeNumber(context, messageId.getAddress()));
- } catch (InvalidNumberException e) {
- Log.w(TAG, e);
- }
+ earlyReceiptCache.increment(messageId.getTimetamp(), messageId.getAddress());
}
} finally {
if (cursor != null)
@@ -273,12 +257,12 @@ public class MmsDatabase extends MessagingDatabase {
private long getThreadIdFor(IncomingMediaMessage retrieved) throws RecipientFormattingException, MmsException {
if (retrieved.getGroupId() != null) {
- Recipients groupRecipients = RecipientFactory.getRecipientsFromString(context, retrieved.getGroupId(), true);
+ Recipients groupRecipients = RecipientFactory.getRecipientsFor(context, new Address[] {retrieved.getGroupId()}, true);
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipients);
}
- String localNumber;
- Set group = new HashSet<>();
+ String localNumber;
+ Set group = new HashSet<>();
if (retrieved.getAddresses().getFrom() == null) {
throw new MmsException("FROM value in PduHeaders did not exist.");
@@ -292,11 +276,11 @@ public class MmsDatabase extends MessagingDatabase {
localNumber = ServiceUtil.getTelephonyManager(context).getLine1Number();
}
- for (String cc : retrieved.getAddresses().getCc()) {
+ for (Address cc : retrieved.getAddresses().getCc()) {
PhoneNumberUtil.MatchType match;
if (localNumber == null) match = PhoneNumberUtil.MatchType.NO_MATCH;
- else match = PhoneNumberUtil.getInstance().isNumberMatch(localNumber, cc);
+ else match = PhoneNumberUtil.getInstance().isNumberMatch(localNumber, cc.toPhoneString());
if (match == PhoneNumberUtil.MatchType.NO_MATCH ||
match == PhoneNumberUtil.MatchType.NOT_A_NUMBER)
@@ -307,11 +291,11 @@ public class MmsDatabase extends MessagingDatabase {
if (retrieved.getAddresses().getTo().size() > 1) {
- for (String to : retrieved.getAddresses().getTo()) {
+ for (Address to : retrieved.getAddresses().getTo()) {
PhoneNumberUtil.MatchType match;
if (localNumber == null) match = PhoneNumberUtil.MatchType.NO_MATCH;
- else match = PhoneNumberUtil.getInstance().isNumberMatch(localNumber, to);
+ else match = PhoneNumberUtil.getInstance().isNumberMatch(localNumber, to.toPhoneString());
if (match == PhoneNumberUtil.MatchType.NO_MATCH ||
match == PhoneNumberUtil.MatchType.NOT_A_NUMBER)
@@ -322,8 +306,7 @@ public class MmsDatabase extends MessagingDatabase {
}
}
- String recipientsList = Util.join(group, ",");
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, recipientsList, false);
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, group.toArray(new Address[0]), false);
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
}
@@ -332,8 +315,7 @@ public class MmsDatabase extends MessagingDatabase {
String fromString = notification.getFrom() != null && notification.getFrom().getTextString() != null
? Util.toIsoString(notification.getFrom().getTextString())
: "";
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, fromString, false);
- if (recipients.isEmpty()) recipients = RecipientFactory.getRecipientsFor(context, Recipient.getUnknownRecipient(), false);
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, fromString)}, false);
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
}
@@ -486,7 +468,7 @@ public class MmsDatabase extends MessagingDatabase {
while(cursor != null && cursor.moveToNext()) {
if (Types.isSecureType(cursor.getLong(3))) {
- SyncMessageId syncMessageId = new SyncMessageId(cursor.getString(1), cursor.getLong(2));
+ SyncMessageId syncMessageId = new SyncMessageId(Address.fromSerialized(cursor.getString(1)), cursor.getLong(2));
ExpirationInfo expirationInfo = new ExpirationInfo(cursor.getLong(0), cursor.getLong(4), cursor.getLong(5), true);
result.add(new MarkedMessageInfo(syncMessageId, expirationInfo));
@@ -516,34 +498,29 @@ public class MmsDatabase extends MessagingDatabase {
cursor = database.query(TABLE_NAME, new String[] {ID, THREAD_ID, MESSAGE_BOX, EXPIRES_IN}, DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())}, null, null, null, null);
while (cursor.moveToNext()) {
- List addresses = addressDatabase.getAddressesListForId(cursor.getLong(cursor.getColumnIndexOrThrow(ID)));
+ List addresses = addressDatabase.getAddressesListForId(cursor.getLong(cursor.getColumnIndexOrThrow(ID)));
- for (String storedAddress : addresses) {
- try {
- String ourAddress = canonicalizeNumber(context, messageId.getAddress());
- String theirAddress = canonicalizeNumberOrGroup(context, storedAddress);
+ for (Address theirAddress : addresses) {
+ Address ourAddress = messageId.getAddress();
- if (ourAddress.equals(theirAddress) || GroupUtil.isEncodedGroup(theirAddress)) {
- long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
- long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
- long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN));
+ if (ourAddress.equals(theirAddress) || theirAddress.isGroup()) {
+ long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
+ long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
+ long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN));
- ContentValues values = new ContentValues();
- values.put(READ, 1);
+ ContentValues values = new ContentValues();
+ values.put(READ, 1);
- if (expiresIn > 0) {
- values.put(EXPIRE_STARTED, expireStarted);
- expiring.add(new Pair<>(id, expiresIn));
- }
-
- database.update(TABLE_NAME, values, ID_WHERE, new String[]{String.valueOf(id)});
-
- DatabaseFactory.getThreadDatabase(context).updateReadState(threadId);
- DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
- notifyConversationListeners(threadId);
+ if (expiresIn > 0) {
+ values.put(EXPIRE_STARTED, expireStarted);
+ expiring.add(new Pair<>(id, expiresIn));
}
- } catch (InvalidNumberException e) {
- Log.w("MmsDatabase", e);
+
+ database.update(TABLE_NAME, values, ID_WHERE, new String[]{String.valueOf(id)});
+
+ DatabaseFactory.getThreadDatabase(context).updateReadState(threadId);
+ DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
+ notifyConversationListeners(threadId);
}
}
}
@@ -630,14 +607,14 @@ public class MmsDatabase extends MessagingDatabase {
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN));
List attachments = new LinkedList(attachmentDatabase.getAttachmentsForMessage(masterSecret, messageId));
MmsAddresses addresses = addr.getAddressesForId(messageId);
- List destinations = new LinkedList<>();
+ List destinations = new LinkedList<>();
String body = getDecryptedBody(masterSecret, messageText, outboxType);
destinations.addAll(addresses.getBcc());
destinations.addAll(addresses.getCc());
destinations.addAll(addresses.getTo());
- Recipients recipients = RecipientFactory.getRecipientsFromStrings(context, destinations, false);
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, destinations.toArray(new Address[0]), false);
if (body != null && (Types.isGroupQuit(outboxType) || Types.isGroupUpdate(outboxType))) {
return new OutgoingGroupMediaMessage(recipients, body, attachments, timestamp, 0);
@@ -668,7 +645,7 @@ public class MmsDatabase extends MessagingDatabase {
try {
OutgoingMediaMessage request = getOutgoingMessage(masterSecret, messageId);
ContentValues contentValues = new ContentValues();
- contentValues.put(ADDRESS, request.getRecipients().getPrimaryRecipient().getNumber());
+ contentValues.put(ADDRESS, request.getRecipients().getPrimaryRecipient().getAddress().serialize());
contentValues.put(DATE_SENT, request.getSentTimeMillis());
contentValues.put(MESSAGE_BOX, Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT | Types.ENCRYPTION_SYMMETRIC_BIT);
contentValues.put(THREAD_ID, getThreadIdForMessage(messageId));
@@ -697,7 +674,7 @@ public class MmsDatabase extends MessagingDatabase {
}
return insertMediaMessage(new MasterSecretUnion(masterSecret),
- MmsAddresses.forTo(request.getRecipients().toNumberStringList(false)),
+ MmsAddresses.forTo(request.getRecipients().getAddressesList()),
request.getBody(),
attachments,
contentValues,
@@ -726,7 +703,7 @@ public class MmsDatabase extends MessagingDatabase {
ContentValues contentValues = new ContentValues();
contentValues.put(DATE_SENT, retrieved.getSentTimeMillis());
- contentValues.put(ADDRESS, retrieved.getAddresses().getFrom());
+ contentValues.put(ADDRESS, retrieved.getAddresses().getFrom().serialize());
contentValues.put(MESSAGE_BOX, mailbox);
contentValues.put(MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF);
@@ -847,7 +824,7 @@ public class MmsDatabase extends MessagingDatabase {
long messageId = db.insert(TABLE_NAME, null, contentValues);
if (notification.getFrom() != null) {
- addressDatabase.insertAddressesForId(messageId, MmsAddresses.forFrom(Util.toIsoString(notification.getFrom().getTextString())));
+ addressDatabase.insertAddressesForId(messageId, MmsAddresses.forFrom(Address.fromExternal(context, Util.toIsoString(notification.getFrom().getTextString()))));
}
return new Pair<>(messageId, threadId);
@@ -887,7 +864,7 @@ public class MmsDatabase extends MessagingDatabase {
type |= Types.EXPIRATION_TIMER_UPDATE_BIT;
}
- List recipientNumbers = message.getRecipients().toNumberStringList(true);
+ List recipientNumbers = message.getRecipients().getAddressesList();
MmsAddresses addresses;
@@ -911,12 +888,7 @@ public class MmsDatabase extends MessagingDatabase {
contentValues.put(EXPIRES_IN, message.getExpiresIn());
if (message.getRecipients().isSingleRecipient()) {
- try {
- contentValues.put(RECEIPT_COUNT, earlyReceiptCache.remove(message.getSentTimeMillis(),
- canonicalizeNumber(context, message.getRecipients().getPrimaryRecipient().getNumber())));
- } catch (InvalidNumberException e) {
- Log.w(TAG, e);
- }
+ contentValues.put(RECEIPT_COUNT, earlyReceiptCache.remove(message.getSentTimeMillis(), message.getRecipients().getPrimaryRecipient().getAddress()));
}
contentValues.remove(ADDRESS);
@@ -1021,7 +993,7 @@ public class MmsDatabase extends MessagingDatabase {
private boolean isDuplicate(IncomingMediaMessage message, long threadId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = database.query(TABLE_NAME, null, DATE_SENT + " = ? AND " + ADDRESS + " = ? AND " + THREAD_ID + " = ?",
- new String[]{String.valueOf(message.getSentTimeMillis()), message.getAddresses().getFrom(), String.valueOf(threadId)},
+ new String[]{String.valueOf(message.getSentTimeMillis()), message.getAddresses().getFrom().serialize(), String.valueOf(threadId)},
null, null, null, "1");
try {
@@ -1249,21 +1221,21 @@ public class MmsDatabase extends MessagingDatabase {
}
private MediaMmsMessageRecord getMediaMmsMessageRecord(Cursor cursor) {
- long id = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.ID));
- long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_SENT));
- long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_RECEIVED));
- long box = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
- long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.THREAD_ID));
- String address = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS));
- int addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS_DEVICE_ID));
- int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.RECEIPT_COUNT));
- DisplayRecord.Body body = getBody(cursor);
- int partCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.PART_COUNT));
- String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES));
- String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE));
- int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.SUBSCRIPTION_ID));
- long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRES_IN));
- long expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRE_STARTED));
+ long id = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.ID));
+ long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_SENT));
+ long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.NORMALIZED_DATE_RECEIVED));
+ long box = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
+ long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.THREAD_ID));
+ String address = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS));
+ int addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS_DEVICE_ID));
+ int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.RECEIPT_COUNT));
+ DisplayRecord.Body body = getBody(cursor);
+ int partCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.PART_COUNT));
+ String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES));
+ String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE));
+ int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.SUBSCRIPTION_ID));
+ long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRES_IN));
+ long expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRE_STARTED));
Recipients recipients = getRecipientsFor(address);
List mismatches = getMismatchedIdentities(mismatchDocument);
@@ -1276,18 +1248,16 @@ public class MmsDatabase extends MessagingDatabase {
networkFailures, subscriptionId, expiresIn, expireStarted);
}
- private Recipients getRecipientsFor(String address) {
- if (TextUtils.isEmpty(address) || address.equals("insert-address-token")) {
- return RecipientFactory.getRecipientsFor(context, Recipient.getUnknownRecipient(), true);
+ private Recipients getRecipientsFor(String serialized) {
+ Address address;
+
+ if (TextUtils.isEmpty(serialized) || "insert-address-token".equals(serialized)) {
+ address = Address.UNKNOWN;
+ } else {
+ address = Address.fromSerialized(serialized);
+
}
-
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, address, true);
-
- if (recipients == null || recipients.isEmpty()) {
- return RecipientFactory.getRecipientsFor(context, Recipient.getUnknownRecipient(), true);
- }
-
- return recipients;
+ return RecipientFactory.getRecipientsFor(context, new Address[] {address}, true);
}
private List getMismatchedIdentities(String document) {
diff --git a/src/org/thoughtcrime/securesms/database/PlaintextBackupExporter.java b/src/org/thoughtcrime/securesms/database/PlaintextBackupExporter.java
index 46e019f58a..717f4f5026 100644
--- a/src/org/thoughtcrime/securesms/database/PlaintextBackupExporter.java
+++ b/src/org/thoughtcrime/securesms/database/PlaintextBackupExporter.java
@@ -44,7 +44,7 @@ public class PlaintextBackupExporter {
while ((record = reader.getNext()) != null) {
XmlBackup.XmlBackupItem item =
- new XmlBackup.XmlBackupItem(0, record.getIndividualRecipient().getNumber(),
+ new XmlBackup.XmlBackupItem(0, record.getIndividualRecipient().getAddress().serialize(),
record.getIndividualRecipient().getName(),
record.getDateReceived(),
MmsSmsColumns.Types.translateToSystemBaseType(record.getType()),
diff --git a/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java b/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java
index 30b03ab484..f48bcde277 100644
--- a/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java
+++ b/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java
@@ -34,7 +34,7 @@ public class PlaintextBackupImporter {
XmlBackup.XmlBackupItem item;
while ((item = backup.getNext()) != null) {
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, item.getAddress(), false);
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, item.getAddress())}, false);
long threadId = threads.getThreadIdFor(recipients);
SQLiteStatement statement = db.createInsertStatement(transaction);
diff --git a/src/org/thoughtcrime/securesms/database/RecipientPreferenceDatabase.java b/src/org/thoughtcrime/securesms/database/RecipientPreferenceDatabase.java
index 1db7cd083a..5ab76b329a 100644
--- a/src/org/thoughtcrime/securesms/database/RecipientPreferenceDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/RecipientPreferenceDatabase.java
@@ -19,7 +19,6 @@ import org.whispersystems.libsignal.util.guava.Optional;
import java.util.Arrays;
-
public class RecipientPreferenceDatabase extends Database {
private static final String TAG = RecipientPreferenceDatabase.class.getSimpleName();
@@ -27,7 +26,7 @@ public class RecipientPreferenceDatabase extends Database {
private static final String TABLE_NAME = "recipient_preferences";
private static final String ID = "_id";
- private static final String RECIPIENT_IDS = "recipient_ids";
+ private static final String ADDRESSES = "recipient_ids";
private static final String BLOCK = "block";
private static final String NOTIFICATION = "notification";
private static final String VIBRATE = "vibrate";
@@ -58,7 +57,7 @@ public class RecipientPreferenceDatabase extends Database {
public static final String CREATE_TABLE =
"CREATE TABLE " + TABLE_NAME +
" (" + ID + " INTEGER PRIMARY KEY, " +
- RECIPIENT_IDS + " TEXT UNIQUE, " +
+ ADDRESSES + " TEXT UNIQUE, " +
BLOCK + " INTEGER DEFAULT 0," +
NOTIFICATION + " TEXT DEFAULT NULL, " +
VIBRATE + " INTEGER DEFAULT " + VibrateState.DEFAULT.getId() + ", " +
@@ -75,7 +74,7 @@ public class RecipientPreferenceDatabase extends Database {
public Cursor getBlocked() {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
- Cursor cursor = database.query(TABLE_NAME, new String[] {ID, RECIPIENT_IDS}, BLOCK + " = 1",
+ Cursor cursor = database.query(TABLE_NAME, new String[] {ID, ADDRESSES}, BLOCK + " = 1",
null, null, null, null, null);
cursor.setNotificationUri(context.getContentResolver(), Uri.parse(RECIPIENT_PREFERENCES_URI));
@@ -86,15 +85,15 @@ public class RecipientPreferenceDatabase extends Database {
return new BlockedReader(context, cursor);
}
- public Optional getRecipientsPreferences(@NonNull long[] recipients) {
- Arrays.sort(recipients);
+ public Optional getRecipientsPreferences(@NonNull Address[] addresses) {
+ Arrays.sort(addresses);
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = null;
try {
- cursor = database.query(TABLE_NAME, null, RECIPIENT_IDS + " = ?",
- new String[] {Util.join(recipients, " ")},
+ cursor = database.query(TABLE_NAME, null, ADDRESSES + " = ?",
+ new String[] {Util.join(addresses, " ")},
null, null, null);
if (cursor != null && cursor.moveToNext()) {
@@ -188,11 +187,11 @@ public class RecipientPreferenceDatabase extends Database {
database.beginTransaction();
- int updated = database.update(TABLE_NAME, contentValues, RECIPIENT_IDS + " = ?",
- new String[] {String.valueOf(recipients.getSortedIdsString())});
+ int updated = database.update(TABLE_NAME, contentValues, ADDRESSES + " = ?",
+ new String[] {Util.join(recipients.getAddresses(), " ")});
if (updated < 1) {
- contentValues.put(RECIPIENT_IDS, recipients.getSortedIdsString());
+ contentValues.put(ADDRESSES, Util.join(recipients.getAddresses(), " "));
database.insert(TABLE_NAME, null, contentValues);
}
@@ -274,8 +273,15 @@ public class RecipientPreferenceDatabase extends Database {
}
public @NonNull Recipients getCurrent() {
- String recipientIds = cursor.getString(cursor.getColumnIndexOrThrow(RECIPIENT_IDS));
- return RecipientFactory.getRecipientsForIds(context, recipientIds, false);
+ String serialized = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESSES));
+ String[] addresses = serialized.split(" ");
+ Address[] addressList = new Address[addresses.length];
+
+ for (int i=0;i 0) {
- contentValues.put(EXPIRE_STARTED, expireStarted);
- expiring.add(new Pair<>(id, expiresIn));
- }
-
- database.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {cursor.getLong(cursor.getColumnIndexOrThrow(ID)) + ""});
-
- DatabaseFactory.getThreadDatabase(context).updateReadState(threadId);
- DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
- notifyConversationListeners(threadId);
+ if (expiresIn > 0) {
+ contentValues.put(EXPIRE_STARTED, expireStarted);
+ expiring.add(new Pair<>(id, expiresIn));
}
- } catch (InvalidNumberException e) {
- Log.w(TAG, e);
+
+ database.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {cursor.getLong(cursor.getColumnIndexOrThrow(ID)) + ""});
+
+ DatabaseFactory.getThreadDatabase(context).updateReadState(threadId);
+ DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
+ notifyConversationListeners(threadId);
}
}
} finally {
@@ -440,7 +422,7 @@ public class SmsDatabase extends MessagingDatabase {
ContentValues contentValues = new ContentValues();
contentValues.put(TYPE, (record.getType() & ~Types.BASE_TYPE_MASK) | Types.BASE_INBOX_TYPE);
- contentValues.put(ADDRESS, record.getIndividualRecipient().getNumber());
+ contentValues.put(ADDRESS, record.getIndividualRecipient().getAddress().serialize());
contentValues.put(ADDRESS_DEVICE_ID, record.getRecipientDeviceId());
contentValues.put(DATE_RECEIVED, System.currentTimeMillis());
contentValues.put(DATE_SENT, record.getDateSent());
@@ -462,24 +444,24 @@ public class SmsDatabase extends MessagingDatabase {
return new Pair<>(newMessageId, record.getThreadId());
}
- public @NonNull Pair insertReceivedCall(@NonNull String number) {
- return insertCallLog(number, Types.INCOMING_CALL_TYPE, false);
+ public @NonNull Pair insertReceivedCall(@NonNull Address address) {
+ return insertCallLog(address, Types.INCOMING_CALL_TYPE, false);
}
- public @NonNull Pair insertOutgoingCall(@NonNull String number) {
- return insertCallLog(number, Types.OUTGOING_CALL_TYPE, false);
+ public @NonNull Pair insertOutgoingCall(@NonNull Address address) {
+ return insertCallLog(address, Types.OUTGOING_CALL_TYPE, false);
}
- public @NonNull Pair insertMissedCall(@NonNull String number) {
- return insertCallLog(number, Types.MISSED_CALL_TYPE, true);
+ public @NonNull Pair insertMissedCall(@NonNull Address address) {
+ return insertCallLog(address, Types.MISSED_CALL_TYPE, true);
}
- private @NonNull Pair insertCallLog(@NonNull String number, long type, boolean unread) {
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, number, true);
+ private @NonNull Pair insertCallLog(@NonNull Address address, long type, boolean unread) {
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {address}, true);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
ContentValues values = new ContentValues(6);
- values.put(ADDRESS, number);
+ values.put(ADDRESS, address.serialize());
values.put(ADDRESS_DEVICE_ID, 1);
values.put(DATE_RECEIVED, System.currentTimeMillis());
values.put(DATE_SENT, System.currentTimeMillis());
@@ -524,21 +506,14 @@ public class SmsDatabase extends MessagingDatabase {
if (message.isIdentityVerified()) type |= Types.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT;
else if (message.isIdentityDefault()) type |= Types.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT;
- Recipients recipients;
-
- if (message.getSender() != null) {
- recipients = RecipientFactory.getRecipientsFromString(context, message.getSender(), true);
- } else {
- Log.w(TAG, "Sender is null, returning unknown recipient");
- recipients = RecipientFactory.getRecipientsFor(context, Recipient.getUnknownRecipient(), false);
- }
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {message.getSender()}, true);
Recipients groupRecipients;
if (message.getGroupId() == null) {
groupRecipients = null;
} else {
- groupRecipients = RecipientFactory.getRecipientsFromString(context, message.getGroupId(), true);
+ groupRecipients = RecipientFactory.getRecipientsFor(context, new Address[] {message.getGroupId()}, true);
}
boolean unread = (org.thoughtcrime.securesms.util.Util.isDefaultSmsProvider(context) ||
@@ -551,7 +526,7 @@ public class SmsDatabase extends MessagingDatabase {
else threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipients);
ContentValues values = new ContentValues(6);
- values.put(ADDRESS, message.getSender());
+ values.put(ADDRESS, message.getSender().serialize());
values.put(ADDRESS_DEVICE_ID, message.getSenderDeviceId());
values.put(DATE_RECEIVED, System.currentTimeMillis());
values.put(DATE_SENT, message.getSentTimestampMillis());
@@ -614,10 +589,10 @@ public class SmsDatabase extends MessagingDatabase {
if (message.isIdentityVerified()) type |= Types.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT;
else if (message.isIdentityDefault()) type |= Types.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT;
- String address = message.getRecipients().getPrimaryRecipient().getNumber();
+ Address address = message.getRecipients().getPrimaryRecipient().getAddress();
ContentValues contentValues = new ContentValues(6);
- contentValues.put(ADDRESS, PhoneNumberUtils.formatNumber(address));
+ contentValues.put(ADDRESS, address.serialize());
contentValues.put(THREAD_ID, threadId);
contentValues.put(BODY, message.getMessageBody());
contentValues.put(DATE_RECEIVED, System.currentTimeMillis());
@@ -626,12 +601,7 @@ public class SmsDatabase extends MessagingDatabase {
contentValues.put(TYPE, type);
contentValues.put(SUBSCRIPTION_ID, message.getSubscriptionId());
contentValues.put(EXPIRES_IN, message.getExpiresIn());
-
- try {
- contentValues.put(RECEIPT_COUNT, earlyReceiptCache.remove(date, canonicalizeNumber(context, address)));
- } catch (InvalidNumberException e) {
- Log.w(TAG, e);
- }
+ contentValues.put(RECEIPT_COUNT, earlyReceiptCache.remove(date, address));
SQLiteDatabase db = databaseHelper.getWritableDatabase();
long messageId = db.insert(TABLE_NAME, ADDRESS, contentValues);
@@ -671,13 +641,13 @@ public class SmsDatabase extends MessagingDatabase {
return db.query(TABLE_NAME, MESSAGE_PROJECTION, where, null, null, null, null);
}
- public Cursor getEncryptedRogueMessages(Recipient recipient) {
- String selection = TYPE + " & " + Types.ENCRYPTION_REMOTE_NO_SESSION_BIT + " != 0" +
- " AND PHONE_NUMBERS_EQUAL(" + ADDRESS + ", ?)";
- String[] args = {recipient.getNumber()};
- SQLiteDatabase db = databaseHelper.getReadableDatabase();
- return db.query(TABLE_NAME, MESSAGE_PROJECTION, selection, args, null, null, null);
- }
+// public Cursor getEncryptedRogueMessages(Recipient recipient) {
+// String selection = TYPE + " & " + Types.ENCRYPTION_REMOTE_NO_SESSION_BIT + " != 0" +
+// " AND PHONE_NUMBERS_EQUAL(" + ADDRESS + ", ?)";
+// String[] args = {recipient.getNumber()};
+// SQLiteDatabase db = databaseHelper.getReadableDatabase();
+// return db.query(TABLE_NAME, MESSAGE_PROJECTION, selection, args, null, null, null);
+// }
public Cursor getExpirationStartedMessages() {
String where = EXPIRE_STARTED + " > 0";
@@ -706,7 +676,7 @@ public class SmsDatabase extends MessagingDatabase {
private boolean isDuplicate(IncomingTextMessage message, long threadId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = database.query(TABLE_NAME, null, DATE_SENT + " = ? AND " + ADDRESS + " = ? AND " + THREAD_ID + " = ?",
- new String[]{String.valueOf(message.getSentTimestampMillis()), message.getSender(), String.valueOf(threadId)},
+ new String[]{String.valueOf(message.getSentTimestampMillis()), message.getSender().serialize(), String.valueOf(threadId)},
null, null, null, "1");
try {
@@ -843,19 +813,19 @@ public class SmsDatabase extends MessagingDatabase {
}
public SmsMessageRecord getCurrent() {
- long messageId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.ID));
- String address = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS));
- int addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS_DEVICE_ID));
- long type = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.TYPE));
- long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.NORMALIZED_DATE_RECEIVED));
- long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.NORMALIZED_DATE_SENT));
- long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.THREAD_ID));
- int status = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.STATUS));
- int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.RECEIPT_COUNT));
- String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.MISMATCHED_IDENTITIES));
- int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.SUBSCRIPTION_ID));
- long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.EXPIRES_IN));
- long expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.EXPIRE_STARTED));
+ long messageId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.ID));
+ Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS)));
+ int addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS_DEVICE_ID));
+ long type = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.TYPE));
+ long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.NORMALIZED_DATE_RECEIVED));
+ long dateSent = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.NORMALIZED_DATE_SENT));
+ long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.THREAD_ID));
+ int status = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.STATUS));
+ int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.RECEIPT_COUNT));
+ String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.MISMATCHED_IDENTITIES));
+ int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.SUBSCRIPTION_ID));
+ long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.EXPIRES_IN));
+ long expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.EXPIRE_STARTED));
List mismatches = getMismatches(mismatchDocument);
Recipients recipients = getRecipientsFor(address);
@@ -869,19 +839,8 @@ public class SmsDatabase extends MessagingDatabase {
expiresIn, expireStarted);
}
- private Recipients getRecipientsFor(String address) {
- if (address != null) {
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, address, true);
-
- if (recipients == null || recipients.isEmpty()) {
- return RecipientFactory.getRecipientsFor(context, Recipient.getUnknownRecipient(), true);
- }
-
- return recipients;
- } else {
- Log.w(TAG, "getRecipientsFor() address is null");
- return RecipientFactory.getRecipientsFor(context, Recipient.getUnknownRecipient(), true);
- }
+ private Recipients getRecipientsFor(Address address) {
+ return RecipientFactory.getRecipientsFor(context, new Address[] {address}, true);
}
private List getMismatches(String document) {
diff --git a/src/org/thoughtcrime/securesms/database/SmsMigrator.java b/src/org/thoughtcrime/securesms/database/SmsMigrator.java
index f78318b7b0..2fc899142f 100644
--- a/src/org/thoughtcrime/securesms/database/SmsMigrator.java
+++ b/src/org/thoughtcrime/securesms/database/SmsMigrator.java
@@ -27,9 +27,10 @@ import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterCipher;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
-import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
import org.thoughtcrime.securesms.recipients.Recipients;
+import java.util.LinkedList;
+import java.util.List;
import java.util.StringTokenizer;
public class SmsMigrator {
@@ -137,24 +138,20 @@ public class SmsMigrator {
}
private static Recipients getOurRecipients(Context context, String theirRecipients) {
- StringTokenizer tokenizer = new StringTokenizer(theirRecipients.trim(), " ");
- StringBuilder sb = new StringBuilder();
+ StringTokenizer tokenizer = new StringTokenizer(theirRecipients.trim(), " ");
+ List addressList = new LinkedList<>();
while (tokenizer.hasMoreTokens()) {
String theirRecipientId = tokenizer.nextToken();
String address = getTheirCanonicalAddress(context, theirRecipientId);
- if (address == null)
- continue;
-
- if (sb.length() != 0)
- sb.append(',');
-
- sb.append(address);
+ if (address != null) {
+ addressList.add(Address.fromExternal(context, address));
+ }
}
- if (sb.length() == 0) return null;
- else return RecipientFactory.getRecipientsFromString(context, sb.toString(), true);
+ if (addressList.isEmpty()) return null;
+ else return RecipientFactory.getRecipientsFor(context, addressList.toArray(new Address[0]), true);
}
private static String encrypt(MasterSecret masterSecret, String body)
diff --git a/src/org/thoughtcrime/securesms/database/TextSecureDirectory.java b/src/org/thoughtcrime/securesms/database/TextSecureDirectory.java
index f7e1275041..a43849fee7 100644
--- a/src/org/thoughtcrime/securesms/database/TextSecureDirectory.java
+++ b/src/org/thoughtcrime/securesms/database/TextSecureDirectory.java
@@ -7,7 +7,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.text.TextUtils;
+import android.support.annotation.NonNull;
import android.util.Log;
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
@@ -69,10 +69,9 @@ public class TextSecureDirectory {
this.databaseHelper = new DatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
}
- public boolean isSecureTextSupported(String e164number) throws NotInDirectoryException {
- if (e164number == null || e164number.length() == 0) {
- return false;
- }
+ public boolean isSecureTextSupported(@NonNull Address address) throws NotInDirectoryException {
+ if (address.isEmail()) return false;
+ if (address.isGroup()) return true;
SQLiteDatabase db = databaseHelper.getReadableDatabase();
Cursor cursor = null;
@@ -80,7 +79,7 @@ public class TextSecureDirectory {
try {
cursor = db.query(TABLE_NAME,
new String[]{REGISTERED}, NUMBER + " = ?",
- new String[] {e164number}, null, null, null);
+ new String[] {address.serialize()}, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
return cursor.getInt(0) == 1;
@@ -94,55 +93,55 @@ public class TextSecureDirectory {
}
}
- public boolean isSecureVoiceSupported(String e164number) throws NotInDirectoryException {
- if (TextUtils.isEmpty(e164number)) {
- return false;
- }
+// public boolean isSecureVoiceSupported(String e164number) throws NotInDirectoryException {
+// if (TextUtils.isEmpty(e164number)) {
+// return false;
+// }
+//
+// SQLiteDatabase db = databaseHelper.getReadableDatabase();
+// Cursor cursor = null;
+//
+// try {
+// cursor = db.query(TABLE_NAME,
+// new String[]{VOICE}, NUMBER + " = ?",
+// new String[] {e164number}, null, null, null);
+//
+// if (cursor != null && cursor.moveToFirst()) {
+// return cursor.getInt(0) == 1;
+// } else {
+// throw new NotInDirectoryException();
+// }
+//
+// } finally {
+// if (cursor != null)
+// cursor.close();
+// }
+// }
- SQLiteDatabase db = databaseHelper.getReadableDatabase();
- Cursor cursor = null;
-
- try {
- cursor = db.query(TABLE_NAME,
- new String[]{VOICE}, NUMBER + " = ?",
- new String[] {e164number}, null, null, null);
-
- if (cursor != null && cursor.moveToFirst()) {
- return cursor.getInt(0) == 1;
- } else {
- throw new NotInDirectoryException();
- }
-
- } finally {
- if (cursor != null)
- cursor.close();
- }
- }
-
- public boolean isSecureVideoSupported(String e164number) throws NotInDirectoryException {
- if (TextUtils.isEmpty(e164number)) {
- return false;
- }
-
- SQLiteDatabase db = databaseHelper.getReadableDatabase();
- Cursor cursor = null;
-
- try {
- cursor = db.query(TABLE_NAME,
- new String[]{VIDEO}, NUMBER + " = ?",
- new String[] {e164number}, null, null, null);
-
- if (cursor != null && cursor.moveToFirst()) {
- return cursor.getInt(0) == 1;
- } else {
- throw new NotInDirectoryException();
- }
-
- } finally {
- if (cursor != null)
- cursor.close();
- }
- }
+// public boolean isSecureVideoSupported(String e164number) throws NotInDirectoryException {
+// if (TextUtils.isEmpty(e164number)) {
+// return false;
+// }
+//
+// SQLiteDatabase db = databaseHelper.getReadableDatabase();
+// Cursor cursor = null;
+//
+// try {
+// cursor = db.query(TABLE_NAME,
+// new String[]{VIDEO}, NUMBER + " = ?",
+// new String[] {e164number}, null, null, null);
+//
+// if (cursor != null && cursor.moveToFirst()) {
+// return cursor.getInt(0) == 1;
+// } else {
+// throw new NotInDirectoryException();
+// }
+//
+// } finally {
+// if (cursor != null)
+// cursor.close();
+// }
+// }
public String getRelay(String e164number) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
diff --git a/src/org/thoughtcrime/securesms/database/ThreadDatabase.java b/src/org/thoughtcrime/securesms/database/ThreadDatabase.java
index 667d485e46..0340b85c57 100644
--- a/src/org/thoughtcrime/securesms/database/ThreadDatabase.java
+++ b/src/org/thoughtcrime/securesms/database/ThreadDatabase.java
@@ -23,6 +23,7 @@ import android.database.MergeCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
@@ -30,21 +31,17 @@ import android.util.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.crypto.MasterCipher;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
-import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.model.DisplayRecord;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;
-import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.InvalidMessageException;
-import java.util.Arrays;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -57,7 +54,7 @@ public class ThreadDatabase extends Database {
public static final String ID = "_id";
public static final String DATE = "date";
public static final String MESSAGE_COUNT = "message_count";
- public static final String RECIPIENT_IDS = "recipient_ids";
+ public static final String ADDRESSES = "recipient_ids";
public static final String SNIPPET = "snippet";
private static final String SNIPPET_CHARSET = "snippet_cs";
public static final String READ = "read";
@@ -73,7 +70,7 @@ public class ThreadDatabase extends Database {
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" +
ID + " INTEGER PRIMARY KEY, " + DATE + " INTEGER DEFAULT 0, " +
- MESSAGE_COUNT + " INTEGER DEFAULT 0, " + RECIPIENT_IDS + " TEXT, " + SNIPPET + " TEXT, " +
+ MESSAGE_COUNT + " INTEGER DEFAULT 0, " + ADDRESSES + " TEXT, " + SNIPPET + " TEXT, " +
SNIPPET_CHARSET + " INTEGER DEFAULT 0, " + READ + " INTEGER DEFAULT 1, " +
TYPE + " INTEGER DEFAULT 0, " + ERROR + " INTEGER DEFAULT 0, " +
SNIPPET_TYPE + " INTEGER DEFAULT 0, " + SNIPPET_URI + " TEXT DEFAULT NULL, " +
@@ -82,7 +79,7 @@ public class ThreadDatabase extends Database {
LAST_SEEN + " INTEGER DEFAULT 0);";
public static final String[] CREATE_INDEXS = {
- "CREATE INDEX IF NOT EXISTS thread_recipient_ids_index ON " + TABLE_NAME + " (" + RECIPIENT_IDS + ");",
+ "CREATE INDEX IF NOT EXISTS thread_recipient_ids_index ON " + TABLE_NAME + " (" + ADDRESSES + ");",
"CREATE INDEX IF NOT EXISTS archived_count_index ON " + TABLE_NAME + " (" + ARCHIVED + ", " + MESSAGE_COUNT + ");",
};
@@ -90,42 +87,12 @@ public class ThreadDatabase extends Database {
super(context, databaseHelper);
}
- private long[] getRecipientIds(Recipients recipients) {
- Set recipientSet = new HashSet<>();
- List recipientList = recipients.getRecipientsList();
-
- for (Recipient recipient : recipientList) {
- recipientSet.add(recipient.getRecipientId());
- }
-
- long[] recipientArray = new long[recipientSet.size()];
- int i = 0;
-
- for (Long recipientId : recipientSet) {
- recipientArray[i++] = recipientId;
- }
-
- Arrays.sort(recipientArray);
-
- return recipientArray;
- }
-
- private String getRecipientsAsString(long[] recipientIds) {
- StringBuilder sb = new StringBuilder();
- for (int i=0;i 1)
contentValues.put(TYPE, distributionType);
@@ -304,29 +271,24 @@ public class ThreadDatabase extends Database {
notifyConversationListListeners();
}
- public Cursor getFilteredConversationList(List filter) {
+ public Cursor getFilteredConversationList(List filter) {
if (filter == null || filter.size() == 0)
return null;
- List rawRecipientIds = DatabaseFactory.getAddressDatabase(context).getCanonicalAddressIds(filter);
+ SQLiteDatabase db = databaseHelper.getReadableDatabase();
+ List> partitionedAddresses = Util.partition(filter, 900);
+ List cursors = new LinkedList<>();
- if (rawRecipientIds == null || rawRecipientIds.size() == 0)
- return null;
+ for (List addresses : partitionedAddresses) {
+ String selection = ADDRESSES + " = ?";
+ String[] selectionArgs = new String[addresses.size()];
- SQLiteDatabase db = databaseHelper.getReadableDatabase();
- List> partitionedRecipientIds = Util.partition(rawRecipientIds, 900);
- List cursors = new LinkedList<>();
-
- for (List recipientIds : partitionedRecipientIds) {
- String selection = RECIPIENT_IDS + " = ?";
- String[] selectionArgs = new String[recipientIds.size()];
-
- for (int i=0;i {
diff --git a/src/org/thoughtcrime/securesms/database/documents/IdentityKeyMismatchList.java b/src/org/thoughtcrime/securesms/database/documents/IdentityKeyMismatchList.java
index 843ce9d449..eaceb4d93f 100644
--- a/src/org/thoughtcrime/securesms/database/documents/IdentityKeyMismatchList.java
+++ b/src/org/thoughtcrime/securesms/database/documents/IdentityKeyMismatchList.java
@@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.database.documents;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.LinkedList;
@@ -25,6 +26,7 @@ public class IdentityKeyMismatchList implements Document {
}
@Override
+ @JsonIgnore
public List getList() {
return mismatches;
}
diff --git a/src/org/thoughtcrime/securesms/database/documents/NetworkFailure.java b/src/org/thoughtcrime/securesms/database/documents/NetworkFailure.java
index faa3d20af1..6dc87ca794 100644
--- a/src/org/thoughtcrime/securesms/database/documents/NetworkFailure.java
+++ b/src/org/thoughtcrime/securesms/database/documents/NetworkFailure.java
@@ -2,19 +2,21 @@ package org.thoughtcrime.securesms.database.documents;
import com.fasterxml.jackson.annotation.JsonProperty;
+import org.thoughtcrime.securesms.database.Address;
+
public class NetworkFailure {
- @JsonProperty(value = "r")
- private long recipientId;
+ @JsonProperty(value = "a")
+ private String address;
- public NetworkFailure(long recipientId) {
- this.recipientId = recipientId;
+ public NetworkFailure(Address address) {
+ this.address = address.serialize();
}
public NetworkFailure() {}
- public long getRecipientId() {
- return recipientId;
+ public Address getAddress() {
+ return Address.fromSerialized(address);
}
@Override
@@ -22,11 +24,11 @@ public class NetworkFailure {
if (other == null || !(other instanceof NetworkFailure)) return false;
NetworkFailure that = (NetworkFailure)other;
- return this.recipientId == that.recipientId;
+ return this.address.equals(that.address);
}
@Override
public int hashCode() {
- return (int)recipientId;
+ return address.hashCode();
}
}
diff --git a/src/org/thoughtcrime/securesms/database/identity/IdentityRecordList.java b/src/org/thoughtcrime/securesms/database/identity/IdentityRecordList.java
index ad7679c350..4ddc76e333 100644
--- a/src/org/thoughtcrime/securesms/database/identity/IdentityRecordList.java
+++ b/src/org/thoughtcrime/securesms/database/identity/IdentityRecordList.java
@@ -77,7 +77,7 @@ public class IdentityRecordList {
for (IdentityRecord identityRecord : identityRecords) {
if (isUntrusted(identityRecord)) {
- untrusted.add(RecipientFactory.getRecipientForId(context, identityRecord.getRecipientId(), false));
+ untrusted.add(RecipientFactory.getRecipientFor(context, identityRecord.getAddress(), false));
}
}
@@ -101,7 +101,7 @@ public class IdentityRecordList {
for (IdentityRecord identityRecord : identityRecords) {
if (identityRecord.getVerifiedStatus() == VerifiedStatus.UNVERIFIED) {
- unverified.add(RecipientFactory.getRecipientForId(context, identityRecord.getRecipientId(), false));
+ unverified.add(RecipientFactory.getRecipientFor(context, identityRecord.getAddress(), false));
}
}
diff --git a/src/org/thoughtcrime/securesms/database/loaders/ConversationListLoader.java b/src/org/thoughtcrime/securesms/database/loaders/ConversationListLoader.java
index d0ef1de46a..4ffe26a39d 100644
--- a/src/org/thoughtcrime/securesms/database/loaders/ConversationListLoader.java
+++ b/src/org/thoughtcrime/securesms/database/loaders/ConversationListLoader.java
@@ -6,6 +6,7 @@ import android.database.MatrixCursor;
import android.database.MergeCursor;
import org.thoughtcrime.securesms.contacts.ContactAccessor;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.util.AbstractCursorLoader;
@@ -41,7 +42,7 @@ public class ConversationListLoader extends AbstractCursorLoader {
if (archivedCount > 0) {
MatrixCursor switchToArchiveCursor = new MatrixCursor(new String[] {
ThreadDatabase.ID, ThreadDatabase.DATE, ThreadDatabase.MESSAGE_COUNT,
- ThreadDatabase.RECIPIENT_IDS, ThreadDatabase.SNIPPET, ThreadDatabase.READ,
+ ThreadDatabase.ADDRESSES, ThreadDatabase.SNIPPET, ThreadDatabase.READ,
ThreadDatabase.TYPE, ThreadDatabase.SNIPPET_TYPE, ThreadDatabase.SNIPPET_URI,
ThreadDatabase.ARCHIVED, ThreadDatabase.STATUS, ThreadDatabase.RECEIPT_COUNT,
ThreadDatabase.EXPIRES_IN, ThreadDatabase.LAST_SEEN}, 1);
@@ -62,6 +63,12 @@ public class ConversationListLoader extends AbstractCursorLoader {
private Cursor getFilteredConversationList(String filter) {
List numbers = ContactAccessor.getInstance().getNumbersForThreadSearchFilter(context, filter);
- return DatabaseFactory.getThreadDatabase(context).getFilteredConversationList(numbers);
+ List addresses = new LinkedList<>();
+
+ for (String number : numbers) {
+ addresses.add(Address.fromExternal(context, number));
+ }
+
+ return DatabaseFactory.getThreadDatabase(context).getFilteredConversationList(addresses);
}
}
diff --git a/src/org/thoughtcrime/securesms/events/WebRtcViewModel.java b/src/org/thoughtcrime/securesms/events/WebRtcViewModel.java
index 15787d7ce9..325a6730e1 100644
--- a/src/org/thoughtcrime/securesms/events/WebRtcViewModel.java
+++ b/src/org/thoughtcrime/securesms/events/WebRtcViewModel.java
@@ -88,6 +88,6 @@ public class WebRtcViewModel {
}
public String toString() {
- return "[State: " + state + ", recipient: " + recipient.getNumber() + ", identity: " + identityKey + ", remoteVideo: " + remoteVideoEnabled + ", localVideo: " + localVideoEnabled + "]";
+ return "[State: " + state + ", recipient: " + recipient.getAddress() + ", identity: " + identityKey + ", remoteVideo: " + remoteVideoEnabled + ", localVideo: " + localVideoEnabled + "]";
}
}
diff --git a/src/org/thoughtcrime/securesms/groups/GroupManager.java b/src/org/thoughtcrime/securesms/groups/GroupManager.java
index a0fb5aec89..73740ec445 100644
--- a/src/org/thoughtcrime/securesms/groups/GroupManager.java
+++ b/src/org/thoughtcrime/securesms/groups/GroupManager.java
@@ -11,6 +11,7 @@ import com.google.protobuf.ByteString;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.UriAttachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
@@ -24,16 +25,17 @@ import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.signalservice.api.util.InvalidNumberException;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
+import java.util.List;
import java.util.Set;
public class GroupManager {
+
public static @NonNull GroupActionResult createGroup(@NonNull Context context,
@NonNull MasterSecret masterSecret,
@NonNull Set members,
@@ -41,23 +43,23 @@ public class GroupManager {
@Nullable String name)
throws InvalidNumberException
{
- final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
- final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
- final byte[] groupId = groupDatabase.allocateGroupId();
- final Set memberE164Numbers = getE164Numbers(context, members);
+ final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
+ final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
+ final byte[] groupId = groupDatabase.allocateGroupId();
+ final Set memberAddresses = getMemberAddresses(context, members);
- memberE164Numbers.add(TextSecurePreferences.getLocalNumber(context));
- groupDatabase.create(groupId, name, new LinkedList<>(memberE164Numbers), null, null);
+ memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
+ groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null);
groupDatabase.updateAvatar(groupId, avatarBytes);
- return sendGroupUpdate(context, masterSecret, groupId, memberE164Numbers, name, avatarBytes);
+ return sendGroupUpdate(context, masterSecret, groupId, memberAddresses, name, avatarBytes);
}
- private static Set getE164Numbers(Context context, Collection recipients)
+ private static Set getMemberAddresses(Context context, Collection recipients)
throws InvalidNumberException
{
- final Set results = new HashSet<>();
+ final Set results = new HashSet<>();
for (Recipient recipient : recipients) {
- results.add(Util.canonicalizeNumber(context, recipient.getNumber()));
+ results.add(recipient.getAddress());
}
return results;
@@ -71,33 +73,39 @@ public class GroupManager {
@Nullable String name)
throws InvalidNumberException
{
- final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
- final Set memberE164Numbers = getE164Numbers(context, members);
- final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
+ final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
+ final Set memberAddresses = getMemberAddresses(context, members);
+ final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
- memberE164Numbers.add(TextSecurePreferences.getLocalNumber(context));
- groupDatabase.updateMembers(groupId, new LinkedList<>(memberE164Numbers));
+ memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
+ groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
groupDatabase.updateTitle(groupId, name);
groupDatabase.updateAvatar(groupId, avatarBytes);
- return sendGroupUpdate(context, masterSecret, groupId, memberE164Numbers, name, avatarBytes);
+ return sendGroupUpdate(context, masterSecret, groupId, memberAddresses, name, avatarBytes);
}
private static GroupActionResult sendGroupUpdate(@NonNull Context context,
@NonNull MasterSecret masterSecret,
@NonNull byte[] groupId,
- @NonNull Set e164numbers,
+ @NonNull Set members,
@Nullable String groupName,
@Nullable byte[] avatar)
{
Attachment avatarAttachment = null;
- String groupRecipientId = GroupUtil.getEncodedId(groupId);
- Recipients groupRecipient = RecipientFactory.getRecipientsFromString(context, groupRecipientId, false);
+ Address groupAddress = Address.fromSerialized(GroupUtil.getEncodedId(groupId));
+ Recipients groupRecipient = RecipientFactory.getRecipientsFor(context, new Address[]{groupAddress}, false);
+
+ List numbers = new LinkedList<>();
+
+ for (Address member : members) {
+ numbers.add(member.serialize());
+ }
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
.setId(ByteString.copyFrom(groupId))
.setType(GroupContext.Type.UPDATE)
- .addAllMembers(e164numbers);
+ .addAllMembers(numbers);
if (groupName != null) groupContextBuilder.setName(groupName);
GroupContext groupContext = groupContextBuilder.build();
diff --git a/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java b/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java
index 544d7c679d..d9b3ad327c 100644
--- a/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java
+++ b/src/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java
@@ -10,13 +10,15 @@ import com.google.protobuf.ByteString;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase;
-import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
+import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.jobs.AvatarDownloadJob;
import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob;
+import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
@@ -37,8 +39,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
-import org.thoughtcrime.securesms.mms.MmsException;
-
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.AttachmentPointer;
import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
@@ -88,9 +88,16 @@ public class GroupMessageProcessor {
GroupContext.Builder builder = createGroupContext(group);
builder.setType(GroupContext.Type.UPDATE);
- SignalServiceAttachment avatar = group.getAvatar().orNull();
+ SignalServiceAttachment avatar = group.getAvatar().orNull();
+ List members = group.getMembers().isPresent() ? new LinkedList() : null;
- database.create(id, group.getName().orNull(), group.getMembers().orNull(),
+ if (group.getMembers().isPresent()) {
+ for (String member : group.getMembers().get()) {
+ members.add(Address.fromExternal(context, member));
+ }
+ }
+
+ database.create(id, group.getName().orNull(), members,
avatar != null && avatar.isPointer() ? avatar.asPointer() : null,
envelope.getRelay());
@@ -108,24 +115,32 @@ public class GroupMessageProcessor {
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
byte[] id = group.getGroupId();
- Set recordMembers = new HashSet<>(groupRecord.getMembers());
- Set messageMembers = new HashSet<>(group.getMembers().get());
+ Set recordMembers = new HashSet<>(groupRecord.getMembers());
+ Set messageMembers = new HashSet<>();
- Set addedMembers = new HashSet<>(messageMembers);
+ for (String messageMember : group.getMembers().get()) {
+ messageMembers.add(Address.fromExternal(context, messageMember));
+ }
+
+ Set addedMembers = new HashSet<>(messageMembers);
addedMembers.removeAll(recordMembers);
- Set missingMembers = new HashSet<>(recordMembers);
+ Set missingMembers = new HashSet<>(recordMembers);
missingMembers.removeAll(messageMembers);
GroupContext.Builder builder = createGroupContext(group);
builder.setType(GroupContext.Type.UPDATE);
if (addedMembers.size() > 0) {
- Set unionMembers = new HashSet<>(recordMembers);
+ Set unionMembers = new HashSet<>(recordMembers);
unionMembers.addAll(messageMembers);
database.updateMembers(id, new LinkedList<>(unionMembers));
- builder.clearMembers().addAllMembers(addedMembers);
+ builder.clearMembers();
+
+ for (Address addedMember : addedMembers) {
+ builder.addMembers(addedMember.serialize());
+ }
} else {
builder.clearMembers();
}
@@ -171,13 +186,13 @@ public class GroupMessageProcessor {
{
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
byte[] id = group.getGroupId();
- List members = record.getMembers();
+ List members = record.getMembers();
GroupContext.Builder builder = createGroupContext(group);
builder.setType(GroupContext.Type.QUIT);
- if (members.contains(envelope.getSource())) {
- database.remove(id, envelope.getSource());
+ if (members.contains(Address.fromExternal(context, envelope.getSource()))) {
+ database.remove(id, Address.fromExternal(context, envelope.getSource()));
if (outgoing) database.setActive(id, false);
return storeMessage(context, masterSecret, envelope, group, builder.build(), outgoing);
@@ -202,7 +217,8 @@ public class GroupMessageProcessor {
try {
if (outgoing) {
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, GroupUtil.getEncodedId(group.getGroupId()), false);
+ Address addres = Address.fromExternal(context, GroupUtil.getEncodedId(group.getGroupId()));
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {addres}, false);
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(recipients, storage, null, envelope.getTimestamp(), 0);
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
long messageId = mmsDatabase.insertMessageOutbox(masterSecret, outgoingMessage, threadId, false, null);
@@ -213,7 +229,7 @@ public class GroupMessageProcessor {
} else {
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
String body = Base64.encodeBytes(storage.toByteArray());
- IncomingTextMessage incoming = new IncomingTextMessage(envelope.getSource(), envelope.getSourceDevice(), envelope.getTimestamp(), body, Optional.of(group), 0);
+ IncomingTextMessage incoming = new IncomingTextMessage(Address.fromExternal(context, envelope.getSource()), envelope.getSourceDevice(), envelope.getTimestamp(), body, Optional.of(group), 0);
IncomingGroupMessage groupMessage = new IncomingGroupMessage(incoming, storage, body);
Optional insertResult = smsDatabase.insertMessageInbox(masterSecret, groupMessage);
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java
index f8f888a35f..34d933edd2 100644
--- a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java
@@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.mms.ApnUnavailableException;
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
+import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.MmsRadioException;
import org.thoughtcrime.securesms.mms.PartParser;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
@@ -42,8 +43,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
-import org.thoughtcrime.securesms.mms.MmsException;
-
public class MmsDownloadJob extends MasterSecretJob {
private static final String TAG = MmsDownloadJob.class.getSimpleName();
@@ -206,7 +205,7 @@ public class MmsDownloadJob extends MasterSecretJob {
- IncomingMediaMessage message = new IncomingMediaMessage(from, to, cc, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false);
+ IncomingMediaMessage message = new IncomingMediaMessage(context, from, to, cc, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false);
Optional insertResult = database.insertMessageInbox(new MasterSecretUnion(masterSecret),
message, contentLocation, threadId);
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java
index c1c19eddc0..1411299be1 100644
--- a/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java
@@ -10,6 +10,7 @@ import com.google.android.mms.pdu_alt.PduHeaders;
import com.google.android.mms.pdu_alt.PduParser;
import org.thoughtcrime.securesms.ApplicationContext;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
@@ -85,7 +86,7 @@ public class MmsReceiveJob extends ContextJob {
private boolean isBlocked(GenericPdu pdu) {
if (pdu.getFrom() != null && pdu.getFrom().getTextString() != null) {
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, Util.toIsoString(pdu.getFrom().getTextString()), false);
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, Util.toIsoString(pdu.getFrom().getTextString()))}, false);
return recipients.isBlocked();
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
index 0435d7a309..24a356ec40 100644
--- a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
@@ -21,12 +21,14 @@ import com.klinker.android.send_message.Utils;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
import org.thoughtcrime.securesms.mms.MediaConstraints;
+import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.MmsSendResult;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.mms.PartAuthority;
@@ -45,8 +47,6 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.List;
-import org.thoughtcrime.securesms.mms.MmsException;
-
public class MmsSendJob extends SendJob {
private static final long serialVersionUID = 0L;
@@ -171,16 +171,16 @@ public class MmsSendJob extends SendJob {
{
SendReq req = new SendReq();
String lineNumber = Utils.getMyPhoneNumber(context);
- List numbers = message.getRecipients().toNumberStringList(true);
- MediaConstraints mediaConstraints = MediaConstraints.getMmsMediaConstraints(message.getSubscriptionId());
+ Address[] numbers = message.getRecipients().getAddresses();
+ MediaConstraints mediaConstraints = MediaConstraints.getMmsMediaConstraints(message.getSubscriptionId());
List scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
if (!TextUtils.isEmpty(lineNumber)) {
req.setFrom(new EncodedStringValue(lineNumber));
}
- for (String recipient : numbers) {
- req.addTo(new EncodedStringValue(recipient));
+ for (Address recipient : numbers) {
+ req.addTo(new EncodedStringValue(recipient.serialize()));
}
req.setDate(System.currentTimeMillis() / 1000);
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java
index 1a3ee6d81f..84194c0aee 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java
@@ -10,16 +10,13 @@ import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.recipients.Recipients;
-import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
-import org.whispersystems.libsignal.logging.Log;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage;
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.io.IOException;
import java.util.LinkedList;
@@ -57,11 +54,7 @@ public class MultiDeviceBlockedUpdateJob extends MasterSecretJob implements Inje
while ((recipients = reader.getNext()) != null) {
if (recipients.isSingleRecipient()) {
- try {
- blocked.add(Util.canonicalizeNumber(context, recipients.getPrimaryRecipient().getNumber()));
- } catch (InvalidNumberException e) {
- Log.w(TAG, e);
- }
+ blocked.add(recipients.getPrimaryRecipient().getAddress().toPhoneString());
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java
index 8ee0bb751f..252b0e6c2e 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java
@@ -6,13 +6,14 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.ContactsContract;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.text.TextUtils;
import android.util.Log;
import org.thoughtcrime.securesms.contacts.ContactAccessor;
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
@@ -20,9 +21,7 @@ import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalM
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
-import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.libsignal.IdentityKey;
@@ -50,19 +49,19 @@ import javax.inject.Inject;
public class MultiDeviceContactUpdateJob extends MasterSecretJob implements InjectableType {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 2L;
private static final String TAG = MultiDeviceContactUpdateJob.class.getSimpleName();
@Inject transient SignalMessageSenderFactory messageSenderFactory;
- private final long recipientId;
+ private final @Nullable String address;
public MultiDeviceContactUpdateJob(Context context) {
- this(context, -1);
+ this(context, null);
}
- public MultiDeviceContactUpdateJob(Context context, long recipientId) {
+ public MultiDeviceContactUpdateJob(Context context, Address address) {
super(context, JobParameters.newBuilder()
.withRequirement(new NetworkRequirement(context))
.withRequirement(new MasterSecretRequirement(context))
@@ -70,7 +69,7 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
.withPersistence()
.create());
- this.recipientId = recipientId;
+ this.address = address.serialize();
}
@Override
@@ -82,11 +81,11 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
return;
}
- if (recipientId <= 0) generateFullContactUpdate();
- else generateSingleContactUpdate(recipientId);
+ if (address == null) generateFullContactUpdate();
+ else generateSingleContactUpdate(Address.fromSerialized(address));
}
- private void generateSingleContactUpdate(long recipientId)
+ private void generateSingleContactUpdate(@NonNull Address address)
throws IOException, UntrustedIdentityException, NetworkException
{
SignalServiceMessageSender messageSender = messageSenderFactory.create();
@@ -94,11 +93,11 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
try {
DeviceContactsOutputStream out = new DeviceContactsOutputStream(new FileOutputStream(contactDataFile));
- Recipient recipient = RecipientFactory.getRecipientForId(context, recipientId, false);
- Optional identityRecord = DatabaseFactory.getIdentityDatabase(context).getIdentity(recipientId);
+ Recipient recipient = RecipientFactory.getRecipientFor(context, address, false);
+ Optional identityRecord = DatabaseFactory.getIdentityDatabase(context).getIdentity(address);
Optional verifiedMessage = getVerifiedMessage(recipient, identityRecord);
- out.write(new DeviceContact(Util.canonicalizeNumber(context, recipient.getNumber()),
+ out.write(new DeviceContact(address.toPhoneString(),
Optional.fromNullable(recipient.getName()),
getAvatar(recipient.getContactUri()),
Optional.fromNullable(recipient.getColor().serialize()),
@@ -126,14 +125,14 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
for (ContactData contactData : contacts) {
Uri contactUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(contactData.id));
- String number = Util.canonicalizeNumber(context, contactData.numbers.get(0).number);
- Recipient recipient = RecipientFactory.getRecipientsFromString(context, number, true).getPrimaryRecipient();
- Optional identity = DatabaseFactory.getIdentityDatabase(context).getIdentity(recipient.getRecipientId());
+ Address address = Address.fromExternal(context, contactData.numbers.get(0).number);
+ Recipient recipient = RecipientFactory.getRecipientFor(context, address, false);
+ Optional identity = DatabaseFactory.getIdentityDatabase(context).getIdentity(address);
Optional verified = getVerifiedMessage(recipient, identity);
Optional name = Optional.fromNullable(contactData.name);
- Optional color = getColor(number);
+ Optional color = Optional.of(recipient.getColor().serialize());
- out.write(new DeviceContact(number, name, getAvatar(contactUri), color, verified));
+ out.write(new DeviceContact(address.toPhoneString(), name, getAvatar(contactUri), color, verified));
}
out.close();
@@ -161,15 +160,6 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
}
- private Optional getColor(String number) {
- if (!TextUtils.isEmpty(number)) {
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, number, false);
- return Optional.of(recipients.getColor().serialize());
- } else {
- return Optional.absent();
- }
- }
-
private void sendUpdate(SignalServiceMessageSender messageSender, File contactsFile, boolean complete)
throws IOException, UntrustedIdentityException, NetworkException
{
@@ -245,7 +235,7 @@ public class MultiDeviceContactUpdateJob extends MasterSecretJob implements Inje
private Optional getVerifiedMessage(Recipient recipient, Optional identity) throws InvalidNumberException {
if (!identity.isPresent()) return Optional.absent();
- String destination = Util.canonicalizeNumber(context, recipient.getNumber());
+ String destination = recipient.getAddress().toPhoneString();
IdentityKey identityKey = identity.get().getIdentityKey();
VerifiedMessage.VerifiedState state;
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java
index fa015fc32a..b993b19226 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java
@@ -5,6 +5,7 @@ import android.support.annotation.Nullable;
import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
@@ -27,6 +28,8 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
import javax.inject.Inject;
@@ -61,8 +64,14 @@ public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements Inject
reader = DatabaseFactory.getGroupDatabase(context).getGroups();
while ((record = reader.getNext()) != null) {
+ List members = new LinkedList<>();
+
+ for (Address member : record.getMembers()) {
+ members.add(member.serialize());
+ }
+
out.write(new DeviceGroup(record.getId(), Optional.fromNullable(record.getTitle()),
- record.getMembers(), getAvatar(record.getAvatar()),
+ members, getAvatar(record.getAvatar()),
record.isActive()));
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java
index 9f2adacb61..27155cdd6f 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java
@@ -44,7 +44,7 @@ public class MultiDeviceReadUpdateJob extends MasterSecretJob implements Injecta
this.messageIds = new LinkedList<>();
for (SyncMessageId messageId : messageIds) {
- this.messageIds.add(new SerializableSyncMessageId(messageId.getAddress(), messageId.getTimetamp()));
+ this.messageIds.add(new SerializableSyncMessageId(messageId.getAddress().toPhoneString(), messageId.getTimetamp()));
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java
index 6dee591a93..141b60e3cd 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java
@@ -4,11 +4,11 @@ package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.util.Log;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.libsignal.IdentityKey;
@@ -18,7 +18,6 @@ import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.io.IOException;
@@ -38,14 +37,14 @@ public class MultiDeviceVerifiedUpdateJob extends ContextJob implements Injectab
private final VerifiedStatus verifiedStatus;
private final long timestamp;
- public MultiDeviceVerifiedUpdateJob(Context context, String destination, IdentityKey identityKey, VerifiedStatus verifiedStatus) {
+ public MultiDeviceVerifiedUpdateJob(Context context, Address destination, IdentityKey identityKey, VerifiedStatus verifiedStatus) {
super(context, JobParameters.newBuilder()
.withRequirement(new NetworkRequirement(context))
.withPersistence()
.withGroupId("__MULTI_DEVICE_VERIFIED_UPDATE__")
.create());
- this.destination = destination;
+ this.destination = destination.serialize();
this.identityKey = identityKey.serialize();
this.verifiedStatus = verifiedStatus;
this.timestamp = System.currentTimeMillis();
@@ -64,13 +63,13 @@ public class MultiDeviceVerifiedUpdateJob extends ContextJob implements Injectab
return;
}
- String canonicalDestination = Util.canonicalizeNumber(context, destination);
+ Address canonicalDestination = Address.fromSerialized(destination);
VerifiedMessage.VerifiedState verifiedState = getVerifiedState(verifiedStatus);
SignalServiceMessageSender messageSender = messageSenderFactory.create();
- VerifiedMessage verifiedMessage = new VerifiedMessage(canonicalDestination, new IdentityKey(identityKey, 0), verifiedState, timestamp);
+ VerifiedMessage verifiedMessage = new VerifiedMessage(canonicalDestination.toPhoneString(), new IdentityKey(identityKey, 0), verifiedState, timestamp);
messageSender.sendMessage(SignalServiceSyncMessage.forVerified(verifiedMessage));
- } catch (InvalidNumberException | InvalidKeyException e) {
+ } catch (InvalidKeyException e) {
throw new IOException(e);
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
index 8beb4d7399..4fe5f9a6a2 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
@@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.crypto.SecurityEvent;
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase;
@@ -79,6 +80,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptM
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
+import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -92,11 +94,11 @@ public class PushDecryptJob extends ContextJob {
private final long messageId;
private final long smsMessageId;
- public PushDecryptJob(Context context, long pushMessageId, String sender) {
- this(context, pushMessageId, -1, sender);
+ public PushDecryptJob(Context context, long pushMessageId) {
+ this(context, pushMessageId, -1);
}
- public PushDecryptJob(Context context, long pushMessageId, long smsMessageId, String sender) {
+ public PushDecryptJob(Context context, long pushMessageId, long smsMessageId) {
super(context, JobParameters.newBuilder()
.withPersistence()
.withGroupId("__PUSH_DECRYPT_JOB__")
@@ -221,7 +223,7 @@ public class PushDecryptJob extends ContextJob {
Intent intent = new Intent(context, WebRtcCallService.class);
intent.setAction(WebRtcCallService.ACTION_INCOMING_CALL);
intent.putExtra(WebRtcCallService.EXTRA_CALL_ID, message.getId());
- intent.putExtra(WebRtcCallService.EXTRA_REMOTE_NUMBER, envelope.getSource());
+ intent.putExtra(WebRtcCallService.EXTRA_REMOTE_ADDRESS, Address.fromExternal(context, envelope.getSource()));
intent.putExtra(WebRtcCallService.EXTRA_REMOTE_DESCRIPTION, message.getDescription());
intent.putExtra(WebRtcCallService.EXTRA_TIMESTAMP, envelope.getTimestamp());
context.startService(intent);
@@ -235,7 +237,7 @@ public class PushDecryptJob extends ContextJob {
Intent intent = new Intent(context, WebRtcCallService.class);
intent.setAction(WebRtcCallService.ACTION_RESPONSE_MESSAGE);
intent.putExtra(WebRtcCallService.EXTRA_CALL_ID, message.getId());
- intent.putExtra(WebRtcCallService.EXTRA_REMOTE_NUMBER, envelope.getSource());
+ intent.putExtra(WebRtcCallService.EXTRA_REMOTE_ADDRESS, Address.fromExternal(context, envelope.getSource()));
intent.putExtra(WebRtcCallService.EXTRA_REMOTE_DESCRIPTION, message.getDescription());
context.startService(intent);
}
@@ -248,7 +250,7 @@ public class PushDecryptJob extends ContextJob {
Intent intent = new Intent(context, WebRtcCallService.class);
intent.setAction(WebRtcCallService.ACTION_ICE_MESSAGE);
intent.putExtra(WebRtcCallService.EXTRA_CALL_ID, message.getId());
- intent.putExtra(WebRtcCallService.EXTRA_REMOTE_NUMBER, envelope.getSource());
+ intent.putExtra(WebRtcCallService.EXTRA_REMOTE_ADDRESS, Address.fromExternal(context, envelope.getSource()));
intent.putExtra(WebRtcCallService.EXTRA_ICE_SDP, message.getSdp());
intent.putExtra(WebRtcCallService.EXTRA_ICE_SDP_MID, message.getSdpMid());
intent.putExtra(WebRtcCallService.EXTRA_ICE_SDP_LINE_INDEX, message.getSdpMLineIndex());
@@ -267,7 +269,7 @@ public class PushDecryptJob extends ContextJob {
Intent intent = new Intent(context, WebRtcCallService.class);
intent.setAction(WebRtcCallService.ACTION_REMOTE_HANGUP);
intent.putExtra(WebRtcCallService.EXTRA_CALL_ID, message.getId());
- intent.putExtra(WebRtcCallService.EXTRA_REMOTE_NUMBER, envelope.getSource());
+ intent.putExtra(WebRtcCallService.EXTRA_REMOTE_ADDRESS, Address.fromExternal(context, envelope.getSource()));
context.startService(intent);
}
}
@@ -278,7 +280,7 @@ public class PushDecryptJob extends ContextJob {
Intent intent = new Intent(context, WebRtcCallService.class);
intent.setAction(WebRtcCallService.ACTION_REMOTE_BUSY);
intent.putExtra(WebRtcCallService.EXTRA_CALL_ID, message.getId());
- intent.putExtra(WebRtcCallService.EXTRA_REMOTE_NUMBER, envelope.getSource());
+ intent.putExtra(WebRtcCallService.EXTRA_REMOTE_ADDRESS, Address.fromExternal(context, envelope.getSource()));
context.startService(intent);
}
@@ -288,7 +290,7 @@ public class PushDecryptJob extends ContextJob {
@NonNull Optional smsMessageId)
{
EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
- IncomingTextMessage incomingTextMessage = new IncomingTextMessage(envelope.getSource(),
+ IncomingTextMessage incomingTextMessage = new IncomingTextMessage(Address.fromExternal(context, envelope.getSource()),
envelope.getSourceDevice(),
message.getTimestamp(),
"", Optional.absent(), 0);
@@ -328,7 +330,7 @@ public class PushDecryptJob extends ContextJob {
if (recipients.isSingleRecipient() && !recipients.isGroupRecipient()) {
SessionStore sessionStore = new TextSecureSessionStore(context);
- sessionStore.deleteAllSessions(recipients.getPrimaryRecipient().getNumber());
+ sessionStore.deleteAllSessions(recipients.getPrimaryRecipient().getAddress().toPhoneString());
SecurityEvent.broadcastSecurityUpdateEvent(context);
@@ -373,8 +375,10 @@ public class PushDecryptJob extends ContextJob {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
String localNumber = TextSecurePreferences.getLocalNumber(context);
Recipients recipients = getMessageDestination(envelope, message);
- IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret, envelope.getSource(),
- localNumber, message.getTimestamp(), -1,
+ IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret,
+ Address.fromExternal(context, envelope.getSource()),
+ Address.fromSerialized(localNumber),
+ message.getTimestamp(), -1,
message.getExpiresInSeconds() * 1000, true,
Optional.fromNullable(envelope.getRelay()),
Optional.absent(), message.getGroupInfo(),
@@ -458,8 +462,8 @@ public class PushDecryptJob extends ContextJob {
long envelopeTimestamp)
{
for (ReadMessage readMessage : readMessages) {
- List> expiringText = DatabaseFactory.getSmsDatabase(context).setTimestampRead(new SyncMessageId(readMessage.getSender(), readMessage.getTimestamp()), envelopeTimestamp);
- List> expiringMedia = DatabaseFactory.getMmsDatabase(context).setTimestampRead(new SyncMessageId(readMessage.getSender(), readMessage.getTimestamp()), envelopeTimestamp);
+ List> expiringText = DatabaseFactory.getSmsDatabase(context).setTimestampRead(new SyncMessageId(Address.fromExternal(context, readMessage.getSender()), readMessage.getTimestamp()), envelopeTimestamp);
+ List> expiringMedia = DatabaseFactory.getMmsDatabase(context).setTimestampRead(new SyncMessageId(Address.fromExternal(context, readMessage.getSender()), readMessage.getTimestamp()), envelopeTimestamp);
for (Pair expiringMessage : expiringText) {
ApplicationContext.getInstance(context)
@@ -488,8 +492,10 @@ public class PushDecryptJob extends ContextJob {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
String localNumber = TextSecurePreferences.getLocalNumber(context);
Recipients recipients = getMessageDestination(envelope, message);
- IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret, envelope.getSource(),
- localNumber, message.getTimestamp(), -1,
+ IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret,
+ Address.fromExternal(context, envelope.getSource()),
+ Address.fromSerialized(localNumber),
+ message.getTimestamp(), -1,
message.getExpiresInSeconds() * 1000, false,
Optional.fromNullable(envelope.getRelay()),
message.getBody(),
@@ -616,7 +622,7 @@ public class PushDecryptJob extends ContextJob {
if (smsMessageId.isPresent() && !message.getGroupInfo().isPresent()) {
threadId = database.updateBundleMessageBody(masterSecret, smsMessageId.get(), body).second;
} else {
- IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(),
+ IncomingTextMessage textMessage = new IncomingTextMessage(Address.fromExternal(context, envelope.getSource()),
envelope.getSourceDevice(),
message.getTimestamp(), body,
message.getGroupInfo(),
@@ -764,14 +770,14 @@ public class PushDecryptJob extends ContextJob {
{
try {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, envelope.getSource(), false);
- long recipientId = recipients.getPrimaryRecipient().getRecipientId();
+ Address sourceAddress = Address.fromExternal(context, envelope.getSource());
byte[] serialized = envelope.hasLegacyMessage() ? envelope.getLegacyMessage() : envelope.getContent();
PreKeySignalMessage whisperMessage = new PreKeySignalMessage(serialized);
IdentityKey identityKey = whisperMessage.getIdentityKey();
String encoded = Base64.encodeBytes(serialized);
- IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(), envelope.getSourceDevice(),
+ IncomingTextMessage textMessage = new IncomingTextMessage(sourceAddress,
+ envelope.getSourceDevice(),
envelope.getTimestamp(), encoded,
Optional.absent(), 0);
@@ -780,13 +786,13 @@ public class PushDecryptJob extends ContextJob {
Optional insertResult = database.insertMessageInbox(masterSecret, bundleMessage);
if (insertResult.isPresent()) {
- database.setMismatchedIdentity(insertResult.get().getMessageId(), recipientId, identityKey);
+ database.setMismatchedIdentity(insertResult.get().getMessageId(), sourceAddress, identityKey);
MessageNotifier.updateNotification(context, masterSecret.getMasterSecret().orNull(), insertResult.get().getThreadId());
}
} else {
database.updateMessageBody(masterSecret, smsMessageId.get(), encoded);
database.markAsPreKeyBundle(smsMessageId.get());
- database.setMismatchedIdentity(smsMessageId.get(), recipientId, identityKey);
+ database.setMismatchedIdentity(smsMessageId.get(), sourceAddress, identityKey);
}
} catch (InvalidMessageException | InvalidVersionException e) {
throw new AssertionError(e);
@@ -795,7 +801,8 @@ public class PushDecryptJob extends ContextJob {
private Optional insertPlaceholder(@NonNull SignalServiceEnvelope envelope) {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
- IncomingTextMessage textMessage = new IncomingTextMessage(envelope.getSource(), envelope.getSourceDevice(),
+ IncomingTextMessage textMessage = new IncomingTextMessage(Address.fromExternal(context, envelope.getSource()),
+ envelope.getSourceDevice(),
envelope.getTimestamp(), "",
Optional.absent(), 0);
@@ -805,17 +812,17 @@ public class PushDecryptJob extends ContextJob {
private Recipients getSyncMessageDestination(SentTranscriptMessage message) {
if (message.getMessage().getGroupInfo().isPresent()) {
- return RecipientFactory.getRecipientsFromString(context, GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get().getGroupId()), false);
+ return RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get().getGroupId()))}, false);
} else {
- return RecipientFactory.getRecipientsFromString(context, message.getDestination().get(), false);
+ return RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, message.getDestination().get())}, false);
}
}
private Recipients getMessageDestination(SignalServiceEnvelope envelope, SignalServiceDataMessage message) {
if (message.getGroupInfo().isPresent()) {
- return RecipientFactory.getRecipientsFromString(context, GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId()), false);
+ return RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId()))}, false);
} else {
- return RecipientFactory.getRecipientsFromString(context, envelope.getSource(), false);
+ return RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, envelope.getSource())}, false);
}
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java
index dd9709719c..ce57af90a8 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java
@@ -1,11 +1,14 @@
package org.thoughtcrime.securesms.jobs;
import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.util.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
@@ -17,7 +20,6 @@ import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
@@ -51,20 +53,22 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
@Inject transient SignalMessageSenderFactory messageSenderFactory;
- private final long messageId;
- private final long filterRecipientId;
+ private final long messageId;
+ private final long filterRecipientId; // Deprecated
+ private final String filterAddress;
- public PushGroupSendJob(Context context, long messageId, String destination, long filterRecipientId) {
+ public PushGroupSendJob(Context context, long messageId, @NonNull Address destination, @Nullable Address filterAddress) {
super(context, JobParameters.newBuilder()
.withPersistence()
- .withGroupId(destination)
+ .withGroupId(destination.toGroupString())
.withRequirement(new MasterSecretRequirement(context))
.withRequirement(new NetworkRequirement(context))
.withRetryCount(5)
.create());
this.messageId = messageId;
- this.filterRecipientId = filterRecipientId;
+ this.filterAddress = filterAddress == null ? null :filterAddress.toPhoneString();
+ this.filterRecipientId = -1;
}
@Override
@@ -79,7 +83,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
OutgoingMediaMessage message = database.getOutgoingMessage(masterSecret, messageId);
try {
- deliver(masterSecret, message, filterRecipientId);
+ deliver(masterSecret, message, filterAddress == null ? null : Address.fromSerialized(filterAddress));
database.markAsSent(messageId, true);
markAttachmentsUploaded(messageId, message.getAttachments());
@@ -99,13 +103,11 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
List failures = new LinkedList<>();
for (NetworkFailureException nfe : e.getNetworkExceptions()) {
- Recipient recipient = RecipientFactory.getRecipientsFromString(context, nfe.getE164number(), false).getPrimaryRecipient();
- failures.add(new NetworkFailure(recipient.getRecipientId()));
+ failures.add(new NetworkFailure(Address.fromSerialized(nfe.getE164number())));
}
for (UntrustedIdentityException uie : e.getUntrustedIdentityExceptions()) {
- Recipient recipient = RecipientFactory.getRecipientsFromString(context, uie.getE164Number(), false).getPrimaryRecipient();
- database.addMismatchedIdentity(messageId, recipient.getRecipientId(), uie.getIdentityKey());
+ database.addMismatchedIdentity(messageId, Address.fromSerialized(uie.getE164Number()), uie.getIdentityKey());
}
database.addFailures(messageId, failures);
@@ -131,20 +133,21 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
DatabaseFactory.getMmsDatabase(context).markAsSentFailed(messageId);
}
- private void deliver(MasterSecret masterSecret, OutgoingMediaMessage message, long filterRecipientId)
+ private void deliver(MasterSecret masterSecret, OutgoingMediaMessage message, @Nullable Address filterAddress)
throws IOException, RecipientFormattingException, InvalidNumberException,
EncapsulatedExceptions, UndeliverableMessageException
{
SignalServiceMessageSender messageSender = messageSenderFactory.create();
- byte[] groupId = GroupUtil.getDecodedId(message.getRecipients().getPrimaryRecipient().getNumber());
+ byte[] groupId = GroupUtil.getDecodedId(message.getRecipients().getPrimaryRecipient().getAddress().toGroupString());
Recipients recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();
List scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
List attachmentStreams = getAttachmentsFor(masterSecret, scaledAttachments);
+
List addresses;
- if (filterRecipientId >= 0) addresses = getPushAddresses(filterRecipientId);
- else addresses = getPushAddresses(recipients);
+ if (filterAddress != null) addresses = getPushAddresses(filterAddress);
+ else addresses = getPushAddresses(recipients);
if (message.isGroup()) {
OutgoingGroupMediaMessage groupMessage = (OutgoingGroupMediaMessage) message;
@@ -166,20 +169,19 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
}
}
- private List getPushAddresses(Recipients recipients) throws InvalidNumberException {
+ private List getPushAddresses(Address address) {
+ List addresses = new LinkedList<>();
+ addresses.add(getPushAddress(address));
+ return addresses;
+ }
+
+ private List getPushAddresses(Recipients recipients) {
List addresses = new LinkedList<>();
for (Recipient recipient : recipients.getRecipientsList()) {
- addresses.add(getPushAddress(recipient.getNumber()));
+ addresses.add(getPushAddress(recipient.getAddress()));
}
return addresses;
}
-
- private List getPushAddresses(long filterRecipientId) throws InvalidNumberException {
- List addresses = new LinkedList<>();
- addresses.add(getPushAddress(RecipientFactory.getRecipientForId(context, filterRecipientId, false).getNumber()));
- return addresses;
- }
-
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java
index f7a132d50f..30d30703de 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java
@@ -4,6 +4,7 @@ package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.util.Log;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
@@ -23,6 +24,8 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
import javax.inject.Inject;
@@ -72,11 +75,16 @@ public class PushGroupUpdateJob extends ContextJob implements InjectableType {
.build();
}
+ List members = new LinkedList<>();
+
+ for (Address member : record.getMembers()) {
+ members.add(member.serialize());
+ }
SignalServiceGroup groupContext = SignalServiceGroup.newBuilder(Type.UPDATE)
.withAvatar(avatar)
.withId(groupId)
- .withMembers(record.getMembers())
+ .withMembers(members)
.withName(record.getTitle())
.build();
diff --git a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
index d0d63ab294..9c538b1f14 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
@@ -6,14 +6,14 @@ import android.util.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.mms.MediaConstraints;
+import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
-import org.thoughtcrime.securesms.recipients.RecipientFactory;
-import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
import org.thoughtcrime.securesms.transport.RetryLaterException;
@@ -24,7 +24,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -32,8 +31,6 @@ import java.util.List;
import javax.inject.Inject;
-import org.thoughtcrime.securesms.mms.MmsException;
-
import static org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
public class PushMediaSendJob extends PushSendJob implements InjectableType {
@@ -46,7 +43,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
private final long messageId;
- public PushMediaSendJob(Context context, long messageId, String destination) {
+ public PushMediaSendJob(Context context, long messageId, Address destination) {
super(context, constructParameters(context, destination));
this.messageId = messageId;
}
@@ -82,10 +79,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context));
} catch (UntrustedIdentityException uie) {
Log.w(TAG, uie);
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, uie.getE164Number(), false);
- long recipientId = recipients.getPrimaryRecipient().getRecipientId();
-
- database.addMismatchedIdentity(messageId, recipientId, uie.getIdentityKey());
+ database.addMismatchedIdentity(messageId, Address.fromSerialized(uie.getE164Number()), uie.getIdentityKey());
database.markAsSentFailed(messageId);
}
}
@@ -108,17 +102,14 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
throws RetryLaterException, InsecureFallbackApprovalException, UntrustedIdentityException,
UndeliverableMessageException
{
- if (message.getRecipients() == null ||
- message.getRecipients().getPrimaryRecipient() == null ||
- message.getRecipients().getPrimaryRecipient().getNumber() == null)
- {
+ if (message.getRecipients() == null || message.getRecipients().getPrimaryRecipient() == null) {
throw new UndeliverableMessageException("No destination address.");
}
SignalServiceMessageSender messageSender = messageSenderFactory.create();
try {
- SignalServiceAddress address = getPushAddress(message.getRecipients().getPrimaryRecipient().getNumber());
+ SignalServiceAddress address = getPushAddress(message.getRecipients().getPrimaryRecipient().getAddress());
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();
List scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
List attachmentStreams = getAttachmentsFor(masterSecret, scaledAttachments);
@@ -131,7 +122,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
.build();
messageSender.sendMessage(address, mediaMessage);
- } catch (InvalidNumberException | UnregisteredUserException e) {
+ } catch (UnregisteredUserException e) {
Log.w(TAG, e);
throw new InsecureFallbackApprovalException(e);
} catch (FileNotFoundException e) {
diff --git a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java
index 0bd5cc94cd..ecf8fc638f 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java
@@ -4,8 +4,8 @@ import android.content.Context;
import android.util.Log;
import org.thoughtcrime.securesms.ApplicationContext;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
-import org.thoughtcrime.securesms.database.MessagingDatabase;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.NotInDirectoryException;
import org.thoughtcrime.securesms.database.TextSecureDirectory;
@@ -26,33 +26,35 @@ public abstract class PushReceivedJob extends ContextJob {
}
public void handle(SignalServiceEnvelope envelope, boolean sendExplicitReceipt) {
- if (!isActiveNumber(context, envelope.getSource())) {
+ Address source = Address.fromExternal(context, envelope.getSource());
+
+ if (!isActiveNumber(context, source)) {
TextSecureDirectory directory = TextSecureDirectory.getInstance(context);
ContactTokenDetails contactTokenDetails = new ContactTokenDetails();
contactTokenDetails.setNumber(envelope.getSource());
directory.setNumber(contactTokenDetails, true);
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, envelope.getSource(), false);
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {source}, false);
ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context, KeyCachingService.getMasterSecret(context), recipients));
}
if (envelope.isReceipt()) {
handleReceipt(envelope);
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage()) {
- handleMessage(envelope, sendExplicitReceipt);
+ handleMessage(envelope, source, sendExplicitReceipt);
} else {
Log.w(TAG, "Received envelope of unknown type: " + envelope.getType());
}
}
- private void handleMessage(SignalServiceEnvelope envelope, boolean sendExplicitReceipt) {
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, envelope.getSource(), false);
+ private void handleMessage(SignalServiceEnvelope envelope, Address source, boolean sendExplicitReceipt) {
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {source}, false);
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
if (!recipients.isBlocked()) {
long messageId = DatabaseFactory.getPushDatabase(context).insert(envelope);
- jobManager.add(new PushDecryptJob(context, messageId, envelope.getSource()));
+ jobManager.add(new PushDecryptJob(context, messageId));
} else {
Log.w(TAG, "*** Received blocked push message, ignoring...");
}
@@ -66,15 +68,15 @@ public abstract class PushReceivedJob extends ContextJob {
private void handleReceipt(SignalServiceEnvelope envelope) {
Log.w(TAG, String.format("Received receipt: (XXXXX, %d)", envelope.getTimestamp()));
- DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(new SyncMessageId(envelope.getSource(),
+ DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()),
envelope.getTimestamp()));
}
- private boolean isActiveNumber(Context context, String e164number) {
+ private boolean isActiveNumber(Context context, Address address) {
boolean isActiveNumber;
try {
- isActiveNumber = TextSecureDirectory.getInstance(context).isSecureTextSupported(e164number);
+ isActiveNumber = TextSecureDirectory.getInstance(context).isSecureTextSupported(address);
} catch (NotInDirectoryException e) {
isActiveNumber = false;
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
index c0104a3cd8..060f19bb41 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
@@ -8,6 +8,7 @@ import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.TextSecureExpiredException;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.TextSecureDirectory;
import org.thoughtcrime.securesms.events.PartProgressEvent;
@@ -16,14 +17,12 @@ import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment.ProgressListener;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.io.IOException;
import java.io.InputStream;
@@ -38,10 +37,10 @@ public abstract class PushSendJob extends SendJob {
super(context, parameters);
}
- protected static JobParameters constructParameters(Context context, String destination) {
+ protected static JobParameters constructParameters(Context context, Address destination) {
JobParameters.Builder builder = JobParameters.newBuilder();
builder.withPersistence();
- builder.withGroupId(destination);
+ builder.withGroupId(destination.serialize());
builder.withRequirement(new MasterSecretRequirement(context));
builder.withRequirement(new NetworkRequirement(context));
builder.withRetryCount(5);
@@ -62,10 +61,9 @@ public abstract class PushSendJob extends SendJob {
onPushSend(masterSecret);
}
- protected SignalServiceAddress getPushAddress(String number) throws InvalidNumberException {
- String e164number = Util.canonicalizeNumber(context, number);
- String relay = TextSecureDirectory.getInstance(context).getRelay(e164number);
- return new SignalServiceAddress(e164number, Optional.fromNullable(relay));
+ protected SignalServiceAddress getPushAddress(Address address) {
+ String relay = TextSecureDirectory.getInstance(context).getRelay(address.toPhoneString());
+ return new SignalServiceAddress(address.toPhoneString(), Optional.fromNullable(relay));
}
protected List getAttachmentsFor(MasterSecret masterSecret, List parts) {
diff --git a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
index 52bce00ddf..402033edc5 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
@@ -5,14 +5,13 @@ import android.util.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
-import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
-import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
@@ -22,7 +21,6 @@ import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.io.IOException;
@@ -40,7 +38,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
private final long messageId;
- public PushTextSendJob(Context context, long messageId, String destination) {
+ public PushTextSendJob(Context context, long messageId, Address destination) {
super(context, constructParameters(context, destination));
this.messageId = messageId;
}
@@ -72,10 +70,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context));
} catch (UntrustedIdentityException e) {
Log.w(TAG, e);
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, e.getE164Number(), false);
- long recipientId = recipients.getPrimaryRecipient().getRecipientId();
-
- database.addMismatchedIdentity(record.getId(), recipientId, e.getIdentityKey());
+ database.addMismatchedIdentity(record.getId(), Address.fromSerialized(e.getE164Number()), e.getIdentityKey());
database.markAsSentFailed(record.getId());
database.markAsPush(record.getId());
}
@@ -104,7 +99,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
throws UntrustedIdentityException, InsecureFallbackApprovalException, RetryLaterException
{
try {
- SignalServiceAddress address = getPushAddress(message.getIndividualRecipient().getNumber());
+ SignalServiceAddress address = getPushAddress(message.getIndividualRecipient().getAddress());
SignalServiceMessageSender messageSender = messageSenderFactory.create();
SignalServiceDataMessage textSecureMessage = SignalServiceDataMessage.newBuilder()
.withTimestamp(message.getDateSent())
@@ -115,7 +110,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
messageSender.sendMessage(address, textSecureMessage);
- } catch (InvalidNumberException | UnregisteredUserException e) {
+ } catch (UnregisteredUserException e) {
Log.w(TAG, e);
throw new InsecureFallbackApprovalException(e);
} catch (IOException e) {
diff --git a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java
index 285aeadeef..1ba656681a 100644
--- a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java
@@ -9,13 +9,11 @@ import android.util.Log;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.service.MessageRetrievalService;
import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.IdentityUtil;
-import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.InvalidKeyException;
@@ -35,14 +33,14 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
@Inject transient SignalServiceMessageReceiver receiver;
- private final long[] recipientIds;
+ private final Recipients recipients;
public RetrieveProfileJob(Context context, Recipients recipients) {
super(context, JobParameters.newBuilder()
.withRetryCount(3)
.create());
- this.recipientIds = recipients.getIds();
+ this.recipients = recipients;
}
@Override
@@ -51,8 +49,6 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
@Override
public void onRun() throws IOException, InvalidKeyException {
try {
- Recipients recipients = RecipientFactory.getRecipientsForIds(context, recipientIds, true);
-
for (Recipient recipient : recipients) {
if (recipient.isGroupRecipient()) handleGroupRecipient(recipient);
else handleIndividualRecipient(recipient);
@@ -73,7 +69,7 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
private void handleIndividualRecipient(Recipient recipient)
throws IOException, InvalidKeyException, InvalidNumberException
{
- String number = Util.canonicalizeNumber(context, recipient.getNumber());
+ String number = recipient.getAddress().toPhoneString();
SignalServiceProfile profile = retrieveProfile(number);
if (TextUtils.isEmpty(profile.getIdentityKey())) {
@@ -84,7 +80,7 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
IdentityKey identityKey = new IdentityKey(Base64.decode(profile.getIdentityKey()), 0);
if (!DatabaseFactory.getIdentityDatabase(context)
- .getIdentity(recipient.getRecipientId())
+ .getIdentity(recipient.getAddress())
.isPresent())
{
Log.w(TAG, "Still first use...");
@@ -97,7 +93,7 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
private void handleGroupRecipient(Recipient group)
throws IOException, InvalidKeyException, InvalidNumberException
{
- byte[] groupId = GroupUtil.getDecodedId(group.getNumber());
+ byte[] groupId = GroupUtil.getDecodedId(group.getAddress().toGroupString());
Recipients recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
for (Recipient recipient : recipients) {
diff --git a/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java
index ae6cee56a1..9959fb9896 100644
--- a/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java
@@ -9,6 +9,7 @@ import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
@@ -85,7 +86,7 @@ public class SmsReceiveJob extends ContextJob {
private boolean isBlocked(IncomingTextMessage message) {
if (message.getSender() != null) {
- Recipients recipients = RecipientFactory.getRecipientsFromString(context, message.getSender(), false);
+ Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {message.getSender()}, false);
return recipients.isBlocked();
}
@@ -114,7 +115,7 @@ public class SmsReceiveJob extends ContextJob {
List messages = new LinkedList<>();
for (Object pdu : pdus) {
- messages.add(new IncomingTextMessage(SmsMessage.createFromPdu((byte[])pdu), subscriptionId));
+ messages.add(new IncomingTextMessage(context, SmsMessage.createFromPdu((byte[])pdu), subscriptionId));
}
if (messages.isEmpty()) {
diff --git a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
index 7b67c8fc7b..62c77d3bc5 100644
--- a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
@@ -80,7 +80,7 @@ public class SmsSendJob extends SendJob {
throw new UndeliverableMessageException("Trying to send a secure SMS?");
}
- String recipient = message.getIndividualRecipient().getNumber();
+ String recipient = message.getIndividualRecipient().getAddress().serialize();
// See issue #1516 for bug report, and discussion on commits related to #4833 for problems
// related to the original fix to #1516. This still may not be a correct fix if networks allow
diff --git a/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java b/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java
index c4a24e18c4..5d2c7ebb38 100644
--- a/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java
@@ -7,8 +7,6 @@ import android.util.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.MasterSecret;
-import org.thoughtcrime.securesms.crypto.SecurityEvent;
-import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
@@ -17,7 +15,6 @@ import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
import org.whispersystems.jobqueue.JobParameters;
-import org.whispersystems.libsignal.state.SessionStore;
public class SmsSentJob extends MasterSecretJob {
@@ -85,7 +82,7 @@ public class SmsSentJob extends MasterSecretJob {
Log.w(TAG, "Service connectivity problem, requeuing...");
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new SmsSendJob(context, messageId, record.getIndividualRecipient().getNumber()));
+ .add(new SmsSendJob(context, messageId, record.getIndividualRecipient().getAddress().serialize()));
break;
default:
database.markAsSentFailed(messageId);
diff --git a/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java b/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java
index ee464b518f..9eae899683 100644
--- a/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java
+++ b/src/org/thoughtcrime/securesms/mms/IncomingMediaMessage.java
@@ -1,8 +1,11 @@
package org.thoughtcrime.securesms.mms;
+import android.content.Context;
+
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.PointerAttachment;
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.MmsAddresses;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.whispersystems.libsignal.util.guava.Optional;
@@ -14,25 +17,25 @@ import java.util.List;
public class IncomingMediaMessage {
- private final String from;
+ private final Address from;
private final String body;
- private final String groupId;
+ private final Address groupId;
private final boolean push;
private final long sentTimeMillis;
private final int subscriptionId;
private final long expiresIn;
private final boolean expirationUpdate;
- private final List to = new LinkedList<>();
- private final List cc = new LinkedList<>();
+ private final List to = new LinkedList<>();
+ private final List cc = new LinkedList<>();
private final List attachments = new LinkedList<>();
- public IncomingMediaMessage(String from, List to, List cc,
+ public IncomingMediaMessage(Context context, String from, List