From 5602a3dfc0501e97b605b1838634d8db1ef5f013 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Tue, 3 Mar 2015 11:44:49 -0800 Subject: [PATCH] Update to latest version of libtextsecure for simplified interface. 1) Switch to new TextSecureAddress addressing, rather than mixing long-based recipient IDs into libtextsecure. 2) Get rid of RecipientFormattingException throws in calls to RecipientFactory. Closes #2570 --- build.gradle | 10 ++-- .../securesms/AutoInitiateActivity.java | 7 +-- .../securesms/ConversationActivity.java | 8 +-- .../securesms/GroupCreateActivity.java | 43 ++++++--------- .../securesms/ImageMediaAdapter.java | 14 ++--- .../securesms/NewConversationActivity.java | 12 ++-- .../securesms/ReceiveKeyActivity.java | 3 +- .../securesms/RoutingActivity.java | 8 +-- .../securesms/VerifyIdentityActivity.java | 7 ++- .../securesms/contacts/RecipientsEditor.java | 8 +-- .../crypto/KeyExchangeInitiator.java | 7 ++- .../securesms/crypto/MmsCipher.java | 17 ++---- .../securesms/crypto/SessionUtil.java | 24 ++++++++ .../securesms/crypto/SmsCipher.java | 29 +++++----- .../storage/TextSecureAxolotlStore.java | 33 +++++------ .../storage/TextSecureIdentityKeyStore.java | 7 ++- .../storage/TextSecureSessionStore.java | 55 +++++++++++-------- .../securesms/database/GroupDatabase.java | 8 +-- .../database/MmsAddressDatabase.java | 8 +-- .../securesms/database/MmsDatabase.java | 23 +++----- .../database/PlaintextBackupImporter.java | 48 ++++++++-------- .../securesms/database/SmsDatabase.java | 23 +++----- .../securesms/database/SmsMigrator.java | 9 +-- .../TextSecureCommunicationModule.java | 22 +++----- .../securesms/jobs/AvatarDownloadJob.java | 10 +--- .../securesms/jobs/DeliveryReceiptJob.java | 4 +- .../securesms/jobs/PushDecryptJob.java | 18 +++--- .../securesms/jobs/PushGroupSendJob.java | 6 +- .../securesms/jobs/PushMediaSendJob.java | 40 +++++--------- .../securesms/jobs/PushSendJob.java | 8 +-- .../securesms/jobs/PushTextSendJob.java | 15 ++--- .../securesms/jobs/SmsSentJob.java | 2 +- .../notifications/MessageNotifier.java | 17 ++---- .../securesms/push/SecurityEventListener.java | 5 +- .../recipients/RecipientFactory.java | 12 +--- .../service/RegistrationService.java | 32 +++++------ .../securesms/util/BitmapWorkerRunnable.java | 40 ++++++-------- 37 files changed, 283 insertions(+), 359 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/crypto/SessionUtil.java diff --git a/build.gradle b/build.gradle index 85369afe5..e613595e2 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ dependencies { compile 'org.whispersystems:jobmanager:0.10.0' compile 'org.whispersystems:libpastelog:1.0.4' - compile 'org.whispersystems:textsecure-android:1.0.0' + compile 'org.whispersystems:textsecure-android:1.1.0' androidTestCompile 'com.google.dexmaker:dexmaker:1.2' androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2' @@ -96,14 +96,14 @@ dependencyVerification { 'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a', 'org.whispersystems:jobmanager:01f35586c43aa3806f1c18d3d6a5a972def98103ba1a5a9ca3eec08d15f974b7', 'org.whispersystems:libpastelog:3ccf00fe1597eb8ca1e5de99b17fc225387a1b80b5bbc00ec1bc4d4f3ea9cdde', - 'org.whispersystems:textsecure-android:af67cb5d8770de6a2ae9c3d64b5ad06b63b24d2d9fb6dc3c4298d7acc60caa2a', + 'org.whispersystems:textsecure-android:d2a8630a796222459163effba01456a322f6f15a63668393fb1203f89180a21a', 'com.android.support:support-annotations:fdee2354787ef66b268e75958de3f7f6c4f8f325510a6dac9f49c929f83a63de', 'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a', 'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f', - 'org.whispersystems:axolotl-android:9cc3328b5a6ca6d407543f3072fd0fbf9080e1ca13ba9d7745f6475d076c2856', - 'org.whispersystems:textsecure-java:bf101047ef41ece9e4dcffdbb0506e185a888c42693d9cb78754d93f01d0c4c7', - 'org.whispersystems:axolotl-java:793556b1397da323ad61d5b6a3efaba464972315d4e3f2e771a9183415aeceaf', + 'org.whispersystems:axolotl-android:68e81fcb2d54626925574740263b8c2501e96f557dabedeeba7fa414deccef99', + 'org.whispersystems:textsecure-java:f552a3cfee5ba111057c700cbe5208a4c7fe31488d17ddf49f01dd974026b00d', + 'org.whispersystems:axolotl-java:4af04115903cbc5581b32ce82d0518a704dd039f48138d26eb518fa3a2bfee91', 'org.whispersystems:curve25519-android:3c29a4131a69b0d16baaa3d707678deb39602c3a3ffd75805ce7f9db252e5d0d', 'com.googlecode.libphonenumber:libphonenumber:eba17eae81dd622ea89a00a3a8c025b2f25d342e0d9644c5b62e16f15687c3ab', 'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74', diff --git a/src/org/thoughtcrime/securesms/AutoInitiateActivity.java b/src/org/thoughtcrime/securesms/AutoInitiateActivity.java index 1cd2029c3..b988c3f81 100644 --- a/src/org/thoughtcrime/securesms/AutoInitiateActivity.java +++ b/src/org/thoughtcrime/securesms/AutoInitiateActivity.java @@ -26,14 +26,12 @@ import android.widget.Button; import org.thoughtcrime.securesms.crypto.KeyExchangeInitiator; import org.thoughtcrime.securesms.crypto.MasterSecret; -import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore; +import org.thoughtcrime.securesms.crypto.SessionUtil; import org.thoughtcrime.securesms.protocol.Tag; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.util.MemoryCleaner; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.libaxolotl.state.SessionStore; -import org.whispersystems.textsecure.api.push.TextSecureAddress; /** * Activity which prompts the user to initiate a secure @@ -117,7 +115,6 @@ public class AutoInitiateActivity extends BaseActivity { MasterSecret masterSecret, Recipient recipient) { - SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret); - return sessionStore.containsSession(recipient.getRecipientId(), TextSecureAddress.DEFAULT_DEVICE_ID); + return SessionUtil.hasSession(context, masterSecret, recipient); } } diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index 57c657230..5cb271335 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -61,7 +61,7 @@ import org.thoughtcrime.securesms.crypto.KeyExchangeInitiator; import org.thoughtcrime.securesms.crypto.MasterCipher; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.SecurityEvent; -import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore; +import org.thoughtcrime.securesms.crypto.SessionUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DraftDatabase; import org.thoughtcrime.securesms.database.DraftDatabase.Draft; @@ -102,8 +102,6 @@ import org.thoughtcrime.securesms.util.MemoryCleaner; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libaxolotl.InvalidMessageException; -import org.whispersystems.libaxolotl.state.SessionStore; -import org.whispersystems.textsecure.api.push.TextSecureAddress; import java.io.IOException; import java.security.NoSuchAlgorithmException; @@ -681,14 +679,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } private void initializeSecurity() { - SessionStore sessionStore = new TextSecureSessionStore(this, masterSecret); Recipient primaryRecipient = getRecipients() == null ? null : getRecipients().getPrimaryRecipient(); boolean isPushDestination = DirectoryHelper.isPushDestination(this, getRecipients()); boolean isSecureSmsAllowed = (!isPushDestination || DirectoryHelper.isSmsFallbackAllowed(this, getRecipients())); boolean isSecureSmsDestination = isSecureSmsAllowed && isSingleConversation() && - sessionStore.containsSession(primaryRecipient.getRecipientId(), - TextSecureAddress.DEFAULT_DEVICE_ID); + SessionUtil.hasSession(this, masterSecret, primaryRecipient); if (isPushDestination || isSecureSmsDestination) { this.isEncryptedConversation = true; diff --git a/src/org/thoughtcrime/securesms/GroupCreateActivity.java b/src/org/thoughtcrime/securesms/GroupCreateActivity.java index d59d97b0d..a8d8f46ad 100644 --- a/src/org/thoughtcrime/securesms/GroupCreateActivity.java +++ b/src/org/thoughtcrime/securesms/GroupCreateActivity.java @@ -383,17 +383,13 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity { List selected = data.getParcelableArrayListExtra("contacts"); for (ContactData contact : selected) { for (ContactAccessor.NumberData numberData : contact.numbers) { - try { - Recipient recipient = RecipientFactory.getRecipientsFromString(this, numberData.number, false) - .getPrimaryRecipient(); + Recipient recipient = RecipientFactory.getRecipientsFromString(this, numberData.number, false) + .getPrimaryRecipient(); - if (!selectedContacts.contains(recipient) && - (existingContacts == null || !existingContacts.contains(recipient)) && - recipient != null) { - addSelectedContact(recipient); - } - } catch (RecipientFormattingException e) { - Log.w(TAG, e); + if (!selectedContacts.contains(recipient) && + (existingContacts == null || !existingContacts.contains(recipient)) && + recipient != null) { + addSelectedContact(recipient); } } } @@ -455,25 +451,20 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity { Set e164numbers) throws InvalidNumberException { + String groupRecipientId = GroupUtil.getEncodedId(groupId); + Recipients groupRecipient = RecipientFactory.getRecipientsFromString(this, groupRecipientId, false); - try { - String groupRecipientId = GroupUtil.getEncodedId(groupId); - Recipients groupRecipient = RecipientFactory.getRecipientsFromString(this, groupRecipientId, false); + GroupContext context = GroupContext.newBuilder() + .setId(ByteString.copyFrom(groupId)) + .setType(GroupContext.Type.UPDATE) + .setName(groupName) + .addAllMembers(e164numbers) + .build(); - GroupContext context = GroupContext.newBuilder() - .setId(ByteString.copyFrom(groupId)) - .setType(GroupContext.Type.UPDATE) - .setName(groupName) - .addAllMembers(e164numbers) - .build(); + OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(this, groupRecipient, context, avatar); + long threadId = MessageSender.send(this, masterSecret, outgoingMessage, -1, false); - OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(this, groupRecipient, context, avatar); - long threadId = MessageSender.send(this, masterSecret, outgoingMessage, -1, false); - - return new Pair<>(threadId, groupRecipient); - } catch (RecipientFormattingException e) { - throw new AssertionError(e); - } + return new Pair<>(threadId, groupRecipient); } private long handleCreateMmsGroup(Set members) { diff --git a/src/org/thoughtcrime/securesms/ImageMediaAdapter.java b/src/org/thoughtcrime/securesms/ImageMediaAdapter.java index 74a7f501f..fd74610bb 100644 --- a/src/org/thoughtcrime/securesms/ImageMediaAdapter.java +++ b/src/org/thoughtcrime/securesms/ImageMediaAdapter.java @@ -99,15 +99,11 @@ public class ImageMediaAdapter extends CursorRecyclerViewAdapter { intent.putExtra(MediaPreviewActivity.DATE_EXTRA, record.getDate()); if (!TextUtils.isEmpty(record.getAddress())) { - try { - Recipients recipients = RecipientFactory.getRecipientsFromString(getContext(), - record.getAddress(), - true); - if (recipients != null && recipients.getPrimaryRecipient() != null) { - intent.putExtra(MediaPreviewActivity.RECIPIENT_EXTRA, recipients.getPrimaryRecipient().getRecipientId()); - } - } catch (RecipientFormattingException rfe) { - Log.w(TAG, rfe); + Recipients recipients = RecipientFactory.getRecipientsFromString(getContext(), + record.getAddress(), + true); + if (recipients != null && recipients.getPrimaryRecipient() != null) { + intent.putExtra(MediaPreviewActivity.RECIPIENT_EXTRA, recipients.getPrimaryRecipient().getRecipientId()); } } intent.setDataAndType(record.getUri(), record.getContentType()); diff --git a/src/org/thoughtcrime/securesms/NewConversationActivity.java b/src/org/thoughtcrime/securesms/NewConversationActivity.java index dd78046b4..660de9569 100644 --- a/src/org/thoughtcrime/securesms/NewConversationActivity.java +++ b/src/org/thoughtcrime/securesms/NewConversationActivity.java @@ -136,14 +136,10 @@ public class NewConversationActivity extends PassphraseRequiredActionBarActivity Recipients recipients = new Recipients(new LinkedList()); for (ContactAccessor.NumberData numberData : contactData.numbers) { if (NumberUtil.isValidSmsOrEmailOrGroup(numberData.number)) { - try { - Recipients recipientsForNumber = RecipientFactory.getRecipientsFromString(NewConversationActivity.this, - numberData.number, - false); - recipients.getRecipientsList().addAll(recipientsForNumber.getRecipientsList()); - } catch (RecipientFormattingException rfe) { - Log.w(TAG, "Caught RecipientFormattingException when trying to convert a selected number to a Recipient.", rfe); - } + Recipients recipientsForNumber = RecipientFactory.getRecipientsFromString(NewConversationActivity.this, + numberData.number, + false); + recipients.getRecipientsList().addAll(recipientsForNumber.getRecipientsList()); } } return recipients; diff --git a/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java b/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java index ad916747b..d95a74b15 100644 --- a/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java +++ b/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java @@ -136,10 +136,9 @@ public class ReceiveKeyActivity extends BaseActivity { } private boolean isTrusted(IdentityKey identityKey) { - long recipientId = recipient.getRecipientId(); IdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(this, masterSecret); - return identityKeyStore.isTrustedIdentity(recipientId, identityKey); + return identityKeyStore.isTrustedIdentity(recipient.getNumber(), identityKey); } private void initializeKey() diff --git a/src/org/thoughtcrime/securesms/RoutingActivity.java b/src/org/thoughtcrime/securesms/RoutingActivity.java index 7d5e87f95..a4f09ed5e 100644 --- a/src/org/thoughtcrime/securesms/RoutingActivity.java +++ b/src/org/thoughtcrime/securesms/RoutingActivity.java @@ -198,12 +198,12 @@ public class RoutingActivity extends PassphraseRequiredActionBarActivity { Recipients recipients; String body = getIntent().getStringExtra("sms_body"); long threadId = getIntent().getLongExtra("thread_id", -1); + Uri data = getIntent().getData(); - try { - String data = getIntent().getData().getSchemeSpecificPart(); - recipients = RecipientFactory.getRecipientsFromString(this, data, false); + if (data != null && data.getSchemeSpecificPart() != null) { + recipients = RecipientFactory.getRecipientsFromString(this, data.getSchemeSpecificPart(), false); threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients); - } catch (RecipientFormattingException rfe) { + } else { recipients = null; } diff --git a/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java b/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java index 10e11f561..432ba8a56 100644 --- a/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java +++ b/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java @@ -30,6 +30,7 @@ import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.MemoryCleaner; +import org.whispersystems.libaxolotl.AxolotlAddress; import org.whispersystems.libaxolotl.IdentityKey; import org.whispersystems.libaxolotl.state.SessionRecord; import org.whispersystems.libaxolotl.state.SessionStore; @@ -183,9 +184,9 @@ public class VerifyIdentityActivity extends KeyScanningActivity { } private IdentityKey getRemoteIdentityKey(MasterSecret masterSecret, Recipient recipient) { - SessionStore sessionStore = new TextSecureSessionStore(this, masterSecret); - SessionRecord record = sessionStore.loadSession(recipient.getRecipientId(), - TextSecureAddress.DEFAULT_DEVICE_ID); + SessionStore sessionStore = new TextSecureSessionStore(this, masterSecret); + AxolotlAddress axolotlAddress = new AxolotlAddress(recipient.getNumber(), TextSecureAddress.DEFAULT_DEVICE_ID); + SessionRecord record = sessionStore.loadSession(axolotlAddress); if (record == null) { return null; diff --git a/src/org/thoughtcrime/securesms/contacts/RecipientsEditor.java b/src/org/thoughtcrime/securesms/contacts/RecipientsEditor.java index f18a36818..12d6f1fb1 100644 --- a/src/org/thoughtcrime/securesms/contacts/RecipientsEditor.java +++ b/src/org/thoughtcrime/securesms/contacts/RecipientsEditor.java @@ -128,13 +128,7 @@ public class RecipientsEditor extends MultiAutoCompleteTextView { } public Recipients constructContactsFromInput() { - Recipients r = null; - try { - r = RecipientFactory.getRecipientsFromString(mContext, mTokenizer.getRawString(), false); - } catch (RecipientFormattingException e) { - Log.w( "RecipientsEditor", e); - } - return r; + return RecipientFactory.getRecipientsFromString(mContext, mTokenizer.getRawString(), false); } private boolean isValidAddress(String number, boolean isMms) { diff --git a/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java b/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java index 544632012..66e4ea0e5 100644 --- a/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java +++ b/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java @@ -30,6 +30,7 @@ import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.OutgoingKeyExchangeMessage; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.Dialogs; +import org.whispersystems.libaxolotl.AxolotlAddress; import org.whispersystems.libaxolotl.SessionBuilder; import org.whispersystems.libaxolotl.protocol.KeyExchangeMessage; import org.whispersystems.libaxolotl.state.IdentityKeyStore; @@ -67,8 +68,8 @@ public class KeyExchangeInitiator { IdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(context, masterSecret); SessionBuilder sessionBuilder = new SessionBuilder(sessionStore, preKeyStore, signedPreKeyStore, - identityKeyStore, recipient.getRecipientId(), - TextSecureAddress.DEFAULT_DEVICE_ID); + identityKeyStore, new AxolotlAddress(recipient.getNumber(), + TextSecureAddress.DEFAULT_DEVICE_ID)); KeyExchangeMessage keyExchangeMessage = sessionBuilder.process(); String serializedMessage = Base64.encodeBytesWithoutPadding(keyExchangeMessage.serialize()); @@ -81,7 +82,7 @@ public class KeyExchangeInitiator { Recipient recipient) { SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret); - SessionRecord sessionRecord = sessionStore.loadSession(recipient.getRecipientId(), TextSecureAddress.DEFAULT_DEVICE_ID); + SessionRecord sessionRecord = sessionStore.loadSession(new AxolotlAddress(recipient.getNumber(), TextSecureAddress.DEFAULT_DEVICE_ID)); return sessionRecord.getSessionState().hasPendingKeyExchange(); } diff --git a/src/org/thoughtcrime/securesms/crypto/MmsCipher.java b/src/org/thoughtcrime/securesms/crypto/MmsCipher.java index 3d12f3bbf..fcdfe5a52 100644 --- a/src/org/thoughtcrime/securesms/crypto/MmsCipher.java +++ b/src/org/thoughtcrime/securesms/crypto/MmsCipher.java @@ -5,11 +5,10 @@ import android.util.Log; import org.thoughtcrime.securesms.mms.TextTransport; import org.thoughtcrime.securesms.protocol.WirePrefix; -import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.RecipientFormattingException; -import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.transport.UndeliverableMessageException; import org.thoughtcrime.securesms.util.Util; +import org.whispersystems.libaxolotl.AxolotlAddress; import org.whispersystems.libaxolotl.DuplicateMessageException; import org.whispersystems.libaxolotl.InvalidMessageException; import org.whispersystems.libaxolotl.LegacyMessageException; @@ -49,9 +48,7 @@ public class MmsCipher { NoSessionException { try { - Recipients recipients = RecipientFactory.getRecipientsFromString(context, pdu.getFrom().getString(), false); - long recipientId = recipients.getPrimaryRecipient().getRecipientId(); - SessionCipher sessionCipher = new SessionCipher(axolotlStore, recipientId, 1); + SessionCipher sessionCipher = new SessionCipher(axolotlStore, new AxolotlAddress(pdu.getFrom().getString(), TextSecureAddress.DEFAULT_DEVICE_ID)); Optional ciphertext = getEncryptedData(pdu); if (!ciphertext.isPresent()) { @@ -83,7 +80,7 @@ public class MmsCipher { MultimediaMessagePdu plaintextGenericPdu = (MultimediaMessagePdu) new PduParser(plaintext).parse(); return new RetrieveConf(plaintextGenericPdu.getPduHeaders(), plaintextGenericPdu.getBody()); - } catch (RecipientFormattingException | IOException e) { + } catch (IOException e) { throw new InvalidMessageException(e); } } @@ -93,19 +90,17 @@ public class MmsCipher { { EncodedStringValue[] encodedRecipient = message.getTo(); String recipientString = encodedRecipient[0].getString(); - Recipients recipients = RecipientFactory.getRecipientsFromString(context, recipientString, false); - long recipientId = recipients.getPrimaryRecipient().getRecipientId(); byte[] pduBytes = new PduComposer(context, message).make(); if (pduBytes == null) { throw new UndeliverableMessageException("PDU composition failed, null payload"); } - if (!axolotlStore.containsSession(recipientId, TextSecureAddress.DEFAULT_DEVICE_ID)) { - throw new NoSessionException("No session for: " + recipientId); + if (!axolotlStore.containsSession(new AxolotlAddress(recipientString, TextSecureAddress.DEFAULT_DEVICE_ID))) { + throw new NoSessionException("No session for: " + recipientString); } - SessionCipher cipher = new SessionCipher(axolotlStore, recipientId, TextSecureAddress.DEFAULT_DEVICE_ID); + SessionCipher cipher = new SessionCipher(axolotlStore, new AxolotlAddress(recipientString, TextSecureAddress.DEFAULT_DEVICE_ID)); CiphertextMessage ciphertextMessage = cipher.encrypt(pduBytes); byte[] encryptedPduBytes = textTransport.getEncodedMessage(ciphertextMessage.serialize()); diff --git a/src/org/thoughtcrime/securesms/crypto/SessionUtil.java b/src/org/thoughtcrime/securesms/crypto/SessionUtil.java new file mode 100644 index 000000000..3953643db --- /dev/null +++ b/src/org/thoughtcrime/securesms/crypto/SessionUtil.java @@ -0,0 +1,24 @@ +package org.thoughtcrime.securesms.crypto; + +import android.content.Context; +import android.support.annotation.NonNull; + +import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore; +import org.thoughtcrime.securesms.recipients.Recipient; +import org.whispersystems.libaxolotl.AxolotlAddress; +import org.whispersystems.libaxolotl.state.SessionStore; +import org.whispersystems.textsecure.api.push.TextSecureAddress; + +public class SessionUtil { + + public static boolean hasSession(Context context, MasterSecret masterSecret, Recipient recipient) { + return hasSession(context, masterSecret, recipient.getNumber()); + } + + public static boolean hasSession(Context context, MasterSecret masterSecret, @NonNull String number) { + SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret); + AxolotlAddress axolotlAddress = new AxolotlAddress(number, TextSecureAddress.DEFAULT_DEVICE_ID); + + return sessionStore.containsSession(axolotlAddress); + } +} diff --git a/src/org/thoughtcrime/securesms/crypto/SmsCipher.java b/src/org/thoughtcrime/securesms/crypto/SmsCipher.java index 80f4334da..e04d70d66 100644 --- a/src/org/thoughtcrime/securesms/crypto/SmsCipher.java +++ b/src/org/thoughtcrime/securesms/crypto/SmsCipher.java @@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.sms.OutgoingKeyExchangeMessage; import org.thoughtcrime.securesms.sms.OutgoingPrekeyBundleMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.sms.SmsTransportDetails; +import org.whispersystems.libaxolotl.AxolotlAddress; import org.whispersystems.libaxolotl.DuplicateMessageException; import org.whispersystems.libaxolotl.InvalidKeyException; import org.whispersystems.libaxolotl.InvalidKeyIdException; @@ -49,20 +50,18 @@ public class SmsCipher { DuplicateMessageException, NoSessionException { try { - Recipients recipients = RecipientFactory.getRecipientsFromString(context, message.getSender(), false); - long recipientId = recipients.getPrimaryRecipient().getRecipientId(); byte[] decoded = transportDetails.getDecodedMessage(message.getMessageBody().getBytes()); WhisperMessage whisperMessage = new WhisperMessage(decoded); - SessionCipher sessionCipher = new SessionCipher(axolotlStore, recipientId, 1); + SessionCipher sessionCipher = new SessionCipher(axolotlStore, new AxolotlAddress(message.getSender(), TextSecureAddress.DEFAULT_DEVICE_ID)); byte[] padded = sessionCipher.decrypt(whisperMessage); byte[] plaintext = transportDetails.getStrippedPaddingMessageBody(padded); if (message.isEndSession() && "TERMINATE".equals(new String(plaintext))) { - axolotlStore.deleteSession(recipientId, 1); + axolotlStore.deleteSession(new AxolotlAddress(message.getSender(), TextSecureAddress.DEFAULT_DEVICE_ID)); } return message.withMessageBody(new String(plaintext)); - } catch (RecipientFormattingException | IOException e) { + } catch (IOException e) { throw new InvalidMessageException(e); } } @@ -72,28 +71,27 @@ public class SmsCipher { UntrustedIdentityException, LegacyMessageException { try { - Recipients recipients = RecipientFactory.getRecipientsFromString(context, message.getSender(), false); byte[] decoded = transportDetails.getDecodedMessage(message.getMessageBody().getBytes()); PreKeyWhisperMessage preKeyMessage = new PreKeyWhisperMessage(decoded); - SessionCipher sessionCipher = new SessionCipher(axolotlStore, recipients.getPrimaryRecipient().getRecipientId(), 1); + SessionCipher sessionCipher = new SessionCipher(axolotlStore, new AxolotlAddress(message.getSender(), TextSecureAddress.DEFAULT_DEVICE_ID)); byte[] padded = sessionCipher.decrypt(preKeyMessage); byte[] plaintext = transportDetails.getStrippedPaddingMessageBody(padded); return new IncomingEncryptedMessage(message, new String(plaintext)); - } catch (RecipientFormattingException | IOException | InvalidKeyException | InvalidKeyIdException e) { + } catch (IOException | InvalidKeyException | InvalidKeyIdException e) { throw new InvalidMessageException(e); } } public OutgoingTextMessage encrypt(OutgoingTextMessage message) throws NoSessionException { - byte[] paddedBody = transportDetails.getPaddedMessageBody(message.getMessageBody().getBytes()); - long recipientId = message.getRecipients().getPrimaryRecipient().getRecipientId(); + byte[] paddedBody = transportDetails.getPaddedMessageBody(message.getMessageBody().getBytes()); + String recipientNumber = message.getRecipients().getPrimaryRecipient().getNumber(); - if (!axolotlStore.containsSession(recipientId, TextSecureAddress.DEFAULT_DEVICE_ID)) { - throw new NoSessionException("No session for: " + recipientId); + if (!axolotlStore.containsSession(new AxolotlAddress(recipientNumber, TextSecureAddress.DEFAULT_DEVICE_ID))) { + throw new NoSessionException("No session for: " + recipientNumber); } - SessionCipher cipher = new SessionCipher(axolotlStore, recipientId, TextSecureAddress.DEFAULT_DEVICE_ID); + SessionCipher cipher = new SessionCipher(axolotlStore, new AxolotlAddress(recipientNumber, TextSecureAddress.DEFAULT_DEVICE_ID)); CiphertextMessage ciphertextMessage = cipher.encrypt(paddedBody); String encodedCiphertext = new String(transportDetails.getEncodedMessage(ciphertextMessage.serialize())); @@ -110,8 +108,9 @@ public class SmsCipher { { try { Recipient recipient = RecipientFactory.getRecipientsFromString(context, message.getSender(), false).getPrimaryRecipient(); + AxolotlAddress axolotlAddress = new AxolotlAddress(message.getSender(), TextSecureAddress.DEFAULT_DEVICE_ID); KeyExchangeMessage exchangeMessage = new KeyExchangeMessage(transportDetails.getDecodedMessage(message.getMessageBody().getBytes())); - SessionBuilder sessionBuilder = new SessionBuilder(axolotlStore, recipient.getRecipientId(), 1); + SessionBuilder sessionBuilder = new SessionBuilder(axolotlStore, axolotlAddress); KeyExchangeMessage response = sessionBuilder.process(exchangeMessage); @@ -121,7 +120,7 @@ public class SmsCipher { } else { return null; } - } catch (RecipientFormattingException | IOException | InvalidKeyException e) { + } catch (IOException | InvalidKeyException e) { throw new InvalidMessageException(e); } } diff --git a/src/org/thoughtcrime/securesms/crypto/storage/TextSecureAxolotlStore.java b/src/org/thoughtcrime/securesms/crypto/storage/TextSecureAxolotlStore.java index 82322cc02..8da6dcf1a 100644 --- a/src/org/thoughtcrime/securesms/crypto/storage/TextSecureAxolotlStore.java +++ b/src/org/thoughtcrime/securesms/crypto/storage/TextSecureAxolotlStore.java @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.crypto.storage; import android.content.Context; import org.thoughtcrime.securesms.crypto.MasterSecret; +import org.whispersystems.libaxolotl.AxolotlAddress; import org.whispersystems.libaxolotl.IdentityKey; import org.whispersystems.libaxolotl.IdentityKeyPair; import org.whispersystems.libaxolotl.InvalidKeyIdException; @@ -42,13 +43,13 @@ public class TextSecureAxolotlStore implements AxolotlStore { } @Override - public void saveIdentity(long recipientId, IdentityKey identityKey) { - identityKeyStore.saveIdentity(recipientId, identityKey); + public void saveIdentity(String number, IdentityKey identityKey) { + identityKeyStore.saveIdentity(number, identityKey); } @Override - public boolean isTrustedIdentity(long recipientId, IdentityKey identityKey) { - return identityKeyStore.isTrustedIdentity(recipientId, identityKey); + public boolean isTrustedIdentity(String number, IdentityKey identityKey) { + return identityKeyStore.isTrustedIdentity(number, identityKey); } @Override @@ -72,33 +73,33 @@ public class TextSecureAxolotlStore implements AxolotlStore { } @Override - public SessionRecord loadSession(long recipientId, int deviceId) { - return sessionStore.loadSession(recipientId, deviceId); + public SessionRecord loadSession(AxolotlAddress axolotlAddress) { + return sessionStore.loadSession(axolotlAddress); } @Override - public List getSubDeviceSessions(long recipientId) { - return sessionStore.getSubDeviceSessions(recipientId); + public List getSubDeviceSessions(String number) { + return sessionStore.getSubDeviceSessions(number); } @Override - public void storeSession(long recipientId, int deviceId, SessionRecord record) { - sessionStore.storeSession(recipientId, deviceId, record); + public void storeSession(AxolotlAddress axolotlAddress, SessionRecord record) { + sessionStore.storeSession(axolotlAddress, record); } @Override - public boolean containsSession(long recipientId, int deviceId) { - return sessionStore.containsSession(recipientId, deviceId); + public boolean containsSession(AxolotlAddress axolotlAddress) { + return sessionStore.containsSession(axolotlAddress); } @Override - public void deleteSession(long recipientId, int deviceId) { - sessionStore.deleteSession(recipientId, deviceId); + public void deleteSession(AxolotlAddress axolotlAddress) { + sessionStore.deleteSession(axolotlAddress); } @Override - public void deleteAllSessions(long recipientId) { - sessionStore.deleteAllSessions(recipientId); + public void deleteAllSessions(String number) { + sessionStore.deleteAllSessions(number); } @Override diff --git a/src/org/thoughtcrime/securesms/crypto/storage/TextSecureIdentityKeyStore.java b/src/org/thoughtcrime/securesms/crypto/storage/TextSecureIdentityKeyStore.java index d033c35c9..48150934c 100644 --- a/src/org/thoughtcrime/securesms/crypto/storage/TextSecureIdentityKeyStore.java +++ b/src/org/thoughtcrime/securesms/crypto/storage/TextSecureIdentityKeyStore.java @@ -5,6 +5,7 @@ import android.content.Context; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.libaxolotl.IdentityKey; import org.whispersystems.libaxolotl.IdentityKeyPair; @@ -31,12 +32,14 @@ public class TextSecureIdentityKeyStore implements IdentityKeyStore { } @Override - public void saveIdentity(long recipientId, IdentityKey identityKey) { + public void saveIdentity(String name, IdentityKey identityKey) { + long recipientId = RecipientFactory.getRecipientsFromString(context, name, true).getPrimaryRecipient().getRecipientId(); DatabaseFactory.getIdentityDatabase(context).saveIdentity(masterSecret, recipientId, identityKey); } @Override - public boolean isTrustedIdentity(long recipientId, IdentityKey identityKey) { + public boolean isTrustedIdentity(String name, IdentityKey identityKey) { + long recipientId = RecipientFactory.getRecipientsFromString(context, name, true).getPrimaryRecipient().getRecipientId(); return DatabaseFactory.getIdentityDatabase(context) .isValidIdentity(masterSecret, recipientId, identityKey); } diff --git a/src/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java b/src/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java index 02227220a..30e62e531 100644 --- a/src/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java +++ b/src/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java @@ -5,12 +5,15 @@ 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.libaxolotl.AxolotlAddress; import org.whispersystems.libaxolotl.InvalidMessageException; import org.whispersystems.libaxolotl.state.SessionRecord; import org.whispersystems.libaxolotl.state.SessionState; import org.whispersystems.libaxolotl.state.SessionStore; import org.whispersystems.textsecure.api.push.TextSecureAddress; -import org.thoughtcrime.securesms.util.Conversions; import java.io.File; import java.io.FileInputStream; @@ -42,11 +45,11 @@ public class TextSecureSessionStore implements SessionStore { } @Override - public SessionRecord loadSession(long recipientId, int deviceId) { + public SessionRecord loadSession(AxolotlAddress address) { synchronized (FILE_LOCK) { try { - MasterCipher cipher = new MasterCipher(masterSecret); - FileInputStream in = new FileInputStream(getSessionFile(recipientId, deviceId)); + MasterCipher cipher = new MasterCipher(masterSecret); + FileInputStream in = new FileInputStream(getSessionFile(address)); int versionMarker = readInteger(in); @@ -74,11 +77,11 @@ public class TextSecureSessionStore implements SessionStore { } @Override - public void storeSession(long recipientId, int deviceId, SessionRecord record) { + public void storeSession(AxolotlAddress address, SessionRecord record) { synchronized (FILE_LOCK) { try { MasterCipher masterCipher = new MasterCipher(masterSecret); - RandomAccessFile sessionFile = new RandomAccessFile(getSessionFile(recipientId, deviceId), "rw"); + RandomAccessFile sessionFile = new RandomAccessFile(getSessionFile(address), "rw"); FileChannel out = sessionFile.getChannel(); out.position(0); @@ -94,32 +97,33 @@ public class TextSecureSessionStore implements SessionStore { } @Override - public boolean containsSession(long recipientId, int deviceId) { - return getSessionFile(recipientId, deviceId).exists() && - loadSession(recipientId, deviceId).getSessionState().hasSenderChain(); + public boolean containsSession(AxolotlAddress address) { + return getSessionFile(address).exists() && + loadSession(address).getSessionState().hasSenderChain(); } @Override - public void deleteSession(long recipientId, int deviceId) { - getSessionFile(recipientId, deviceId).delete(); + public void deleteSession(AxolotlAddress address) { + getSessionFile(address).delete(); } @Override - public void deleteAllSessions(long recipientId) { - List devices = getSubDeviceSessions(recipientId); + public void deleteAllSessions(String name) { + List devices = getSubDeviceSessions(name); - deleteSession(recipientId, TextSecureAddress.DEFAULT_DEVICE_ID); + deleteSession(new AxolotlAddress(name, TextSecureAddress.DEFAULT_DEVICE_ID)); for (int device : devices) { - deleteSession(recipientId, device); + deleteSession(new AxolotlAddress(name, device)); } } @Override - public List getSubDeviceSessions(long recipientId) { - List results = new LinkedList<>(); - File parent = getSessionDirectory(); - String[] children = parent.list(); + 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(); if (children == null) return results; @@ -132,15 +136,15 @@ public class TextSecureSessionStore implements SessionStore { results.add(Integer.parseInt(parts[1])); } } catch (NumberFormatException e) { - Log.w("SessionRecordV2", e); + Log.w(TAG, e); } } return results; } - private File getSessionFile(long recipientId, int deviceId) { - return new File(getSessionDirectory(), getSessionName(recipientId, deviceId)); + private File getSessionFile(AxolotlAddress address) { + return new File(getSessionDirectory(), getSessionName(address)); } private File getSessionDirectory() { @@ -155,7 +159,12 @@ public class TextSecureSessionStore implements SessionStore { return directory; } - private String getSessionName(long recipientId, int deviceId) { + private String getSessionName(AxolotlAddress axolotlAddress) { + Recipient recipient = RecipientFactory.getRecipientsFromString(context, axolotlAddress.getName(), true) + .getPrimaryRecipient(); + long recipientId = recipient.getRecipientId(); + int deviceId = axolotlAddress.getDeviceId(); + return recipientId + (deviceId == TextSecureAddress.DEFAULT_DEVICE_ID ? "" : "." + deviceId); } diff --git a/src/org/thoughtcrime/securesms/database/GroupDatabase.java b/src/org/thoughtcrime/securesms/database/GroupDatabase.java index 933cc43f1..acd16b7b2 100644 --- a/src/org/thoughtcrime/securesms/database/GroupDatabase.java +++ b/src/org/thoughtcrime/securesms/database/GroupDatabase.java @@ -96,12 +96,8 @@ public class GroupDatabase extends Database { if (!includeSelf && member.equals(localNumber)) continue; - try { - recipients.addAll(RecipientFactory.getRecipientsFromString(context, member, false) - .getRecipientsList()); - } catch (RecipientFormattingException e) { - Log.w("GroupDatabase", e); - } + recipients.addAll(RecipientFactory.getRecipientsFromString(context, member, false) + .getRecipientsList()); } return new Recipients(recipients); diff --git a/src/org/thoughtcrime/securesms/database/MmsAddressDatabase.java b/src/org/thoughtcrime/securesms/database/MmsAddressDatabase.java index 94bcf4646..adc65a067 100644 --- a/src/org/thoughtcrime/securesms/database/MmsAddressDatabase.java +++ b/src/org/thoughtcrime/securesms/database/MmsAddressDatabase.java @@ -140,12 +140,8 @@ public class MmsAddressDatabase extends Database { for (String number : numbers) { if (!PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.equals(number)) { - try { - results.add(RecipientFactory.getRecipientsFromString(context, number, false) - .getPrimaryRecipient()); - } catch (RecipientFormattingException e) { - Log.w(TAG, e); - } + results.add(RecipientFactory.getRecipientsFromString(context, number, false) + .getPrimaryRecipient()); } } diff --git a/src/org/thoughtcrime/securesms/database/MmsDatabase.java b/src/org/thoughtcrime/securesms/database/MmsDatabase.java index b86893298..0096437d5 100644 --- a/src/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -1062,22 +1062,17 @@ public class MmsDatabase extends MessagingDatabase { } private Recipients getRecipientsFor(String address) { - try { - if (TextUtils.isEmpty(address) || address.equals("insert-address-token")) { - return new Recipients(Recipient.getUnknownRecipient(context)); - } - - Recipients recipients = RecipientFactory.getRecipientsFromString(context, address, false); - - if (recipients == null || recipients.isEmpty()) { - return new Recipients(Recipient.getUnknownRecipient(context)); - } - - return recipients; - } catch (RecipientFormattingException e) { - Log.w("MmsDatabase", e); + if (TextUtils.isEmpty(address) || address.equals("insert-address-token")) { return new Recipients(Recipient.getUnknownRecipient(context)); } + + Recipients recipients = RecipientFactory.getRecipientsFromString(context, address, false); + + if (recipients == null || recipients.isEmpty()) { + return new Recipients(Recipient.getUnknownRecipient(context)); + } + + return recipients; } private List getMismatchedIdentities(String document) { diff --git a/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java b/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java index 9f8972d88..ac56bc95d 100644 --- a/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java +++ b/src/org/thoughtcrime/securesms/database/PlaintextBackupImporter.java @@ -55,35 +55,31 @@ public class PlaintextBackupImporter { XmlBackup.XmlBackupItem item; while ((item = backup.getNext()) != null) { - try { - Recipients recipients = RecipientFactory.getRecipientsFromString(context, item.getAddress(), false); - long threadId = threads.getThreadIdFor(recipients); - SQLiteStatement statement = db.createInsertStatement(transaction); + Recipients recipients = RecipientFactory.getRecipientsFromString(context, item.getAddress(), false); + long threadId = threads.getThreadIdFor(recipients); + SQLiteStatement statement = db.createInsertStatement(transaction); - if (item.getAddress() == null || item.getAddress().equals("null")) - continue; + if (item.getAddress() == null || item.getAddress().equals("null")) + continue; - if (!isAppropriateTypeForImport(item.getType())) - continue; + if (!isAppropriateTypeForImport(item.getType())) + continue; - addStringToStatement(statement, 1, item.getAddress()); - addNullToStatement(statement, 2); - addLongToStatement(statement, 3, item.getDate()); - addLongToStatement(statement, 4, item.getDate()); - addLongToStatement(statement, 5, item.getProtocol()); - addLongToStatement(statement, 6, item.getRead()); - addLongToStatement(statement, 7, item.getStatus()); - addTranslatedTypeToStatement(statement, 8, item.getType()); - addNullToStatement(statement, 9); - addStringToStatement(statement, 10, item.getSubject()); - addEncryptedStingToStatement(masterCipher, statement, 11, item.getBody()); - addStringToStatement(statement, 12, item.getServiceCenter()); - addLongToStatement(statement, 13, threadId); - modifiedThreads.add(threadId); - statement.execute(); - } catch (RecipientFormattingException rfe) { - Log.w("PlaintextBackupImporter", rfe); - } + addStringToStatement(statement, 1, item.getAddress()); + addNullToStatement(statement, 2); + addLongToStatement(statement, 3, item.getDate()); + addLongToStatement(statement, 4, item.getDate()); + addLongToStatement(statement, 5, item.getProtocol()); + addLongToStatement(statement, 6, item.getRead()); + addLongToStatement(statement, 7, item.getStatus()); + addTranslatedTypeToStatement(statement, 8, item.getType()); + addNullToStatement(statement, 9); + addStringToStatement(statement, 10, item.getSubject()); + addEncryptedStingToStatement(masterCipher, statement, 11, item.getBody()); + addStringToStatement(statement, 12, item.getServiceCenter()); + addLongToStatement(statement, 13, threadId); + modifiedThreads.add(threadId); + statement.execute(); } for (long threadId : modifiedThreads) { diff --git a/src/org/thoughtcrime/securesms/database/SmsDatabase.java b/src/org/thoughtcrime/securesms/database/SmsDatabase.java index e2ef629d8..84434ea42 100644 --- a/src/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -390,24 +390,19 @@ public class SmsDatabase extends MessagingDatabase { Recipients recipients; - try { + if (message.getSender() != null) { recipients = RecipientFactory.getRecipientsFromString(context, message.getSender(), true); - } catch (RecipientFormattingException e) { - Log.w("SmsDatabase", e); + } else { + Log.w(TAG, "Sender is null, returning unknown recipient"); recipients = new Recipients(Recipient.getUnknownRecipient(context)); } Recipients groupRecipients; - try { - if (message.getGroupId() == null) { - groupRecipients = null; - } else { - groupRecipients = RecipientFactory.getRecipientsFromString(context, message.getGroupId(), true); - } - } catch (RecipientFormattingException e) { - Log.w("SmsDatabase", e); + if (message.getGroupId() == null) { groupRecipients = null; + } else { + groupRecipients = RecipientFactory.getRecipientsFromString(context, message.getGroupId(), true); } boolean unread = org.thoughtcrime.securesms.util.Util.isDefaultSmsProvider(context) || @@ -643,7 +638,7 @@ public class SmsDatabase extends MessagingDatabase { } private Recipients getRecipientsFor(String address) { - try { + if (address != null) { Recipients recipients = RecipientFactory.getRecipientsFromString(context, address, false); if (recipients == null || recipients.isEmpty()) { @@ -651,8 +646,8 @@ public class SmsDatabase extends MessagingDatabase { } return recipients; - } catch (RecipientFormattingException e) { - Log.w("EncryptingSmsDatabase", e); + } else { + Log.w(TAG, "getRecipientsFor() address is null"); return new Recipients(Recipient.getUnknownRecipient(context)); } } diff --git a/src/org/thoughtcrime/securesms/database/SmsMigrator.java b/src/org/thoughtcrime/securesms/database/SmsMigrator.java index 541576259..00840657e 100644 --- a/src/org/thoughtcrime/securesms/database/SmsMigrator.java +++ b/src/org/thoughtcrime/securesms/database/SmsMigrator.java @@ -150,13 +150,8 @@ public class SmsMigrator { sb.append(address); } - try { - if (sb.length() == 0) return null; - else return RecipientFactory.getRecipientsFromString(context, sb.toString(), true); - } catch (RecipientFormattingException rfe) { - Log.w("SmsMigrator", rfe); - return null; - } + if (sb.length() == 0) return null; + else return RecipientFactory.getRecipientsFromString(context, sb.toString(), true); } private static String encrypt(MasterSecret masterSecret, String body) diff --git a/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java b/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java index 9e27d09e6..2405d5164 100644 --- a/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java +++ b/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java @@ -57,21 +57,13 @@ public class TextSecureCommunicationModule { return new TextSecureMessageSenderFactory() { @Override public TextSecureMessageSender create(MasterSecret masterSecret) { - try { - String localNumber = TextSecurePreferences.getLocalNumber(context); - Recipient localRecipient = RecipientFactory.getRecipientsFromString(context, localNumber, false).getPrimaryRecipient(); - - return new TextSecureMessageSender(Release.PUSH_URL, - new TextSecurePushTrustStore(context), - TextSecurePreferences.getLocalNumber(context), - TextSecurePreferences.getPushServerPassword(context), - localRecipient.getRecipientId(), - new TextSecureAxolotlStore(context, masterSecret), - Optional.of((TextSecureMessageSender.EventListener) - new SecurityEventListener(context))); - } catch (RecipientFormattingException e) { - throw new AssertionError(e); - } + return new TextSecureMessageSender(Release.PUSH_URL, + new TextSecurePushTrustStore(context), + TextSecurePreferences.getLocalNumber(context), + TextSecurePreferences.getPushServerPassword(context), + new TextSecureAxolotlStore(context, masterSecret), + Optional.of((TextSecureMessageSender.EventListener) + new SecurityEventListener(context))); } }; } diff --git a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java index 52cd6d4e6..6a7123f49 100644 --- a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java +++ b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java @@ -72,13 +72,9 @@ public class AvatarDownloadJob extends MasterSecretJob { database.updateAvatar(groupId, avatar); - try { - Recipient groupRecipient = RecipientFactory.getRecipientsFromString(context, GroupUtil.getEncodedId(groupId), true) - .getPrimaryRecipient(); - groupRecipient.setContactPhoto(avatar); - } catch (RecipientFormattingException e) { - Log.w("AvatarDownloader", e); - } + Recipient groupRecipient = RecipientFactory.getRecipientsFromString(context, GroupUtil.getEncodedId(groupId), true) + .getPrimaryRecipient(); + groupRecipient.setContactPhoto(avatar); } } catch (InvalidMessageException | BitmapDecodingException | NonSuccessfulResponseCodeException e) { Log.w(TAG, e); diff --git a/src/org/thoughtcrime/securesms/jobs/DeliveryReceiptJob.java b/src/org/thoughtcrime/securesms/jobs/DeliveryReceiptJob.java index d0d09e958..b9c260c98 100644 --- a/src/org/thoughtcrime/securesms/jobs/DeliveryReceiptJob.java +++ b/src/org/thoughtcrime/securesms/jobs/DeliveryReceiptJob.java @@ -3,9 +3,11 @@ package org.thoughtcrime.securesms.jobs; import android.content.Context; import android.util.Log; + import org.thoughtcrime.securesms.dependencies.InjectableType; import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.jobqueue.requirements.NetworkRequirement; +import org.whispersystems.libaxolotl.util.guava.Optional; import org.whispersystems.textsecure.api.TextSecureMessageSender; import org.whispersystems.textsecure.api.push.TextSecureAddress; import org.whispersystems.textsecure.api.push.exceptions.NonSuccessfulResponseCodeException; @@ -46,7 +48,7 @@ public class DeliveryReceiptJob extends ContextJob implements InjectableType { public void onRun() throws IOException { Log.w("DeliveryReceiptJob", "Sending delivery receipt..."); TextSecureMessageSender messageSender = messageSenderFactory.create(null); - TextSecureAddress textSecureAddress = new TextSecureAddress(-1, destination, relay); + TextSecureAddress textSecureAddress = new TextSecureAddress(destination, Optional.fromNullable(relay)); messageSender.sendDeliveryReceipt(textSecureAddress, timestamp); } diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index 2522a81ce..ee971d9e3 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.jobqueue.JobParameters; +import org.whispersystems.libaxolotl.AxolotlAddress; import org.whispersystems.libaxolotl.DuplicateMessageException; import org.whispersystems.libaxolotl.IdentityKey; import org.whispersystems.libaxolotl.InvalidKeyException; @@ -98,15 +99,13 @@ public class PushDecryptJob extends MasterSecretJob { private void handleMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, long smsMessageId) { try { - Recipients recipients = RecipientFactory.getRecipientsFromString(context, envelope.getSource(), false); - long recipientId = recipients.getPrimaryRecipient().getRecipientId(); int deviceId = envelope.getSourceDevice(); AxolotlStore axolotlStore = new TextSecureAxolotlStore(context, masterSecret); - TextSecureCipher cipher = new TextSecureCipher(axolotlStore, recipientId, deviceId); + TextSecureCipher cipher = new TextSecureCipher(axolotlStore, new AxolotlAddress(envelope.getSource(), deviceId)); TextSecureMessage message = cipher.decrypt(envelope); - if (message.isEndSession()) handleEndSessionMessage(masterSecret, recipientId, envelope, message, smsMessageId); + if (message.isEndSession()) handleEndSessionMessage(masterSecret, envelope, message, smsMessageId); else if (message.isGroupUpdate()) handleGroupMessage(masterSecret, envelope, message, smsMessageId); else if (message.getAttachments().isPresent()) handleMediaMessage(masterSecret, envelope, message, smsMessageId); else handleTextMessage(masterSecret, envelope, message, smsMessageId); @@ -117,7 +116,7 @@ public class PushDecryptJob extends MasterSecretJob { } catch (InvalidVersionException e) { Log.w(TAG, e); handleInvalidVersionMessage(masterSecret, envelope, smsMessageId); - } catch (InvalidMessageException | InvalidKeyIdException | InvalidKeyException | MmsException | RecipientFormattingException e) { + } catch (InvalidMessageException | InvalidKeyIdException | InvalidKeyException | MmsException e) { Log.w(TAG, e); handleCorruptMessage(masterSecret, envelope, smsMessageId); } catch (NoSessionException e) { @@ -135,9 +134,8 @@ public class PushDecryptJob extends MasterSecretJob { } } - private void handleEndSessionMessage(MasterSecret masterSecret, long recipientId, - TextSecureEnvelope envelope, TextSecureMessage message, - long smsMessageId) + private void handleEndSessionMessage(MasterSecret masterSecret, TextSecureEnvelope envelope, + TextSecureMessage message, long smsMessageId) { EncryptingSmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context); IncomingTextMessage incomingTextMessage = new IncomingTextMessage(envelope.getSource(), @@ -157,7 +155,7 @@ public class PushDecryptJob extends MasterSecretJob { } SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret); - sessionStore.deleteAllSessions(recipientId); + sessionStore.deleteAllSessions(envelope.getSource()); SecurityEvent.broadcastSecurityUpdateEvent(context, threadId); MessageNotifier.updateNotification(context, masterSecret, threadId); @@ -309,7 +307,7 @@ public class PushDecryptJob extends MasterSecretJob { database.markAsPreKeyBundle(smsMessageId); database.addMismatchedIdentity(smsMessageId, recipientId, identityKey); } - } catch (RecipientFormattingException | InvalidMessageException | InvalidVersionException e) { + } catch (InvalidMessageException | InvalidVersionException e) { throw new AssertionError(e); } } diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java index 7da276134..2b726b810 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java @@ -72,7 +72,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { @Override public void onSend(MasterSecret masterSecret) - throws MmsException, IOException, NoSuchMessageException, RecipientFormattingException + throws MmsException, IOException, NoSuchMessageException { MmsDatabase database = DatabaseFactory.getMmsDatabase(context); SendReq message = database.getOutgoingMessage(masterSecret, messageId); @@ -164,7 +164,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { List addresses = new LinkedList<>(); for (Recipient recipient : recipients.getRecipientsList()) { - addresses.add(getPushAddress(recipient)); + addresses.add(getPushAddress(recipient.getNumber())); } return addresses; @@ -172,7 +172,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { private List getPushAddresses(long filterRecipientId) throws InvalidNumberException { List addresses = new LinkedList<>(); - addresses.add(getPushAddress(RecipientFactory.getRecipientForId(context, filterRecipientId, false))); + addresses.add(getPushAddress(RecipientFactory.getRecipientForId(context, filterRecipientId, false).getNumber())); return addresses; } diff --git a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java index aa4584500..915fdb8f5 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java @@ -5,7 +5,7 @@ import android.util.Log; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.crypto.MasterSecret; -import org.thoughtcrime.securesms.crypto.storage.TextSecureAxolotlStore; +import org.thoughtcrime.securesms.crypto.SessionUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.NoSuchMessageException; @@ -14,13 +14,11 @@ import org.thoughtcrime.securesms.mms.MediaConstraints; import org.thoughtcrime.securesms.mms.PartParser; 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.InsecureFallbackApprovalException; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.transport.SecureFallbackApprovalException; import org.thoughtcrime.securesms.transport.UndeliverableMessageException; -import org.whispersystems.libaxolotl.state.AxolotlStore; import org.whispersystems.textsecure.api.TextSecureMessageSender; import org.whispersystems.textsecure.api.crypto.UntrustedIdentityException; import org.whispersystems.textsecure.api.messages.TextSecureAttachment; @@ -62,7 +60,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType { @Override public void onSend(MasterSecret masterSecret) throws RetryLaterException, MmsException, NoSuchMessageException, - UndeliverableMessageException, RecipientFormattingException + UndeliverableMessageException { MmsDatabase database = DatabaseFactory.getMmsDatabase(context); SendReq message = database.getOutgoingMessage(masterSecret, messageId); @@ -117,8 +115,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType { try { prepareMessageMedia(masterSecret, message, MediaConstraints.PUSH_CONSTRAINTS, false); - Recipients recipients = RecipientFactory.getRecipientsFromString(context, destination, false); - TextSecureAddress address = getPushAddress(recipients.getPrimaryRecipient()); + TextSecureAddress address = getPushAddress(destination); List attachments = getAttachments(masterSecret, message); String body = PartParser.getMessageText(message.getBody()); TextSecureMessage mediaMessage = new TextSecureMessage(message.getSentTimestamp(), attachments, body); @@ -129,7 +126,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType { Log.w(TAG, e); if (isSmsFallbackSupported) fallbackOrAskApproval(masterSecret, message, destination); else database.markAsSentFailed(messageId); - } catch (IOException | RecipientFormattingException e) { + } catch (IOException e) { Log.w(TAG, e); if (isSmsFallbackSupported) fallbackOrAskApproval(masterSecret, message, destination); else throw new RetryLaterException(e); @@ -140,25 +137,18 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType { private void fallbackOrAskApproval(MasterSecret masterSecret, SendReq mediaMessage, String destination) throws SecureFallbackApprovalException, InsecureFallbackApprovalException { - try { - Recipient recipient = RecipientFactory.getRecipientsFromString(context, destination, false).getPrimaryRecipient(); - boolean isSmsFallbackApprovalRequired = isSmsFallbackApprovalRequired(destination, true); - AxolotlStore axolotlStore = new TextSecureAxolotlStore(context, masterSecret); + boolean isSmsFallbackApprovalRequired = isSmsFallbackApprovalRequired(destination, true); - if (!isSmsFallbackApprovalRequired) { - Log.w(TAG, "Falling back to MMS"); - DatabaseFactory.getMmsDatabase(context).markAsForcedSms(mediaMessage.getDatabaseMessageId()); - ApplicationContext.getInstance(context).getJobManager().add(new MmsSendJob(context, messageId)); - } else if (!axolotlStore.containsSession(recipient.getRecipientId(), TextSecureAddress.DEFAULT_DEVICE_ID)) { - Log.w(TAG, "Marking message as pending insecure SMS fallback"); - throw new InsecureFallbackApprovalException("Pending user approval for fallback to insecure SMS"); - } else { - Log.w(TAG, "Marking message as pending secure SMS fallback"); - throw new SecureFallbackApprovalException("Pending user approval for fallback secure to SMS"); - } - } catch (RecipientFormattingException rfe) { - Log.w(TAG, rfe); - DatabaseFactory.getMmsDatabase(context).markAsSentFailed(messageId); + if (!isSmsFallbackApprovalRequired) { + Log.w(TAG, "Falling back to MMS"); + DatabaseFactory.getMmsDatabase(context).markAsForcedSms(mediaMessage.getDatabaseMessageId()); + ApplicationContext.getInstance(context).getJobManager().add(new MmsSendJob(context, messageId)); + } else if (!SessionUtil.hasSession(context, masterSecret, destination)) { + Log.w(TAG, "Marking message as pending insecure SMS fallback"); + throw new InsecureFallbackApprovalException("Pending user approval for fallback to insecure SMS"); + } else { + Log.w(TAG, "Marking message as pending secure SMS fallback"); + throw new SecureFallbackApprovalException("Pending user approval for fallback secure to SMS"); } } diff --git a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java index d7615ec40..0223e8983 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java @@ -9,13 +9,13 @@ import org.thoughtcrime.securesms.database.TextSecureDirectory; import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement; import org.thoughtcrime.securesms.mms.PartAuthority; import org.thoughtcrime.securesms.notifications.MessageNotifier; -import org.thoughtcrime.securesms.recipients.Recipient; 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.jobqueue.JobParameters; import org.whispersystems.jobqueue.requirements.NetworkRequirement; +import org.whispersystems.libaxolotl.util.guava.Optional; import org.whispersystems.textsecure.api.messages.TextSecureAttachment; import org.whispersystems.textsecure.api.messages.TextSecureAttachmentStream; import org.whispersystems.textsecure.api.push.TextSecureAddress; @@ -76,10 +76,10 @@ public abstract class PushSendJob extends SendJob { } } - protected TextSecureAddress getPushAddress(Recipient recipient) throws InvalidNumberException { - String e164number = Util.canonicalizeNumber(context, recipient.getNumber()); + protected TextSecureAddress getPushAddress(String number) throws InvalidNumberException { + String e164number = Util.canonicalizeNumber(context, number); String relay = TextSecureDirectory.getInstance(context).getRelay(e164number); - return new TextSecureAddress(recipient.getRecipientId(), e164number, relay); + return new TextSecureAddress(e164number, Optional.fromNullable(relay)); } protected boolean isSmsFallbackApprovalRequired(String destination, boolean media) { diff --git a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java index 0d652ed7b..e6fadd7bf 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java @@ -5,7 +5,7 @@ import android.util.Log; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.crypto.MasterSecret; -import org.thoughtcrime.securesms.crypto.storage.TextSecureAxolotlStore; +import org.thoughtcrime.securesms.crypto.SessionUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.EncryptingSmsDatabase; import org.thoughtcrime.securesms.database.NoSuchMessageException; @@ -15,12 +15,10 @@ import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.notifications.MessageNotifier; 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.InsecureFallbackApprovalException; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.transport.SecureFallbackApprovalException; -import org.whispersystems.libaxolotl.state.AxolotlStore; import org.whispersystems.textsecure.api.TextSecureMessageSender; import org.whispersystems.textsecure.api.crypto.UntrustedIdentityException; import org.whispersystems.textsecure.api.messages.TextSecureMessage; @@ -55,7 +53,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType { } @Override - public void onSend(MasterSecret masterSecret) throws NoSuchMessageException, RetryLaterException, RecipientFormattingException { + public void onSend(MasterSecret masterSecret) throws NoSuchMessageException, RetryLaterException { EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context); SmsMessageRecord record = database.getMessage(masterSecret, messageId); String destination = record.getIndividualRecipient().getNumber(); @@ -111,7 +109,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType { boolean isSmsFallbackSupported = isSmsFallbackSupported(context, destination, false); try { - TextSecureAddress address = getPushAddress(message.getIndividualRecipient()); + TextSecureAddress address = getPushAddress(message.getIndividualRecipient().getNumber()); TextSecureMessageSender messageSender = messageSenderFactory.create(masterSecret); if (message.isEndSession()) { @@ -138,15 +136,14 @@ public class PushTextSendJob extends PushSendJob implements InjectableType { private void fallbackOrAskApproval(MasterSecret masterSecret, SmsMessageRecord smsMessage, String destination) throws SecureFallbackApprovalException, InsecureFallbackApprovalException { - Recipient recipient = smsMessage.getIndividualRecipient(); - boolean isSmsFallbackApprovalRequired = isSmsFallbackApprovalRequired(destination, false); - AxolotlStore axolotlStore = new TextSecureAxolotlStore(context, masterSecret); + Recipient recipient = smsMessage.getIndividualRecipient(); + boolean isSmsFallbackApprovalRequired = isSmsFallbackApprovalRequired(destination, false); if (!isSmsFallbackApprovalRequired) { Log.w(TAG, "Falling back to SMS"); DatabaseFactory.getSmsDatabase(context).markAsForcedSms(smsMessage.getId()); ApplicationContext.getInstance(context).getJobManager().add(new SmsSendJob(context, messageId, destination)); - } else if (!axolotlStore.containsSession(recipient.getRecipientId(), TextSecureAddress.DEFAULT_DEVICE_ID)) { + } else if (!SessionUtil.hasSession(context, masterSecret, recipient)) { Log.w(TAG, "Marking message as pending insecure fallback."); throw new InsecureFallbackApprovalException("Pending user approval for fallback to insecure SMS"); } else { diff --git a/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java b/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java index 322e72195..4899c5110 100644 --- a/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java +++ b/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java @@ -83,7 +83,7 @@ public class SmsSentJob extends MasterSecretJob { if (record != null && record.isEndSession()) { Log.w(TAG, "Ending session..."); SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret); - sessionStore.deleteAllSessions(record.getIndividualRecipient().getRecipientId()); + sessionStore.deleteAllSessions(record.getIndividualRecipient().getNumber()); SecurityEvent.broadcastSecurityUpdateEvent(context, record.getThreadId()); } diff --git a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java index 1fb124aef..f14a4b807 100644 --- a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java +++ b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java @@ -49,7 +49,6 @@ import org.thoughtcrime.securesms.database.SmsDatabase; import org.thoughtcrime.securesms.database.model.MessageRecord; 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.service.KeyCachingService; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -311,18 +310,10 @@ public class MessageNotifier { reader = DatabaseFactory.getPushDatabase(context).readerFor(cursor); while ((envelope = reader.getNext()) != null) { - Recipients recipients; - - try { - recipients = RecipientFactory.getRecipientsFromString(context, envelope.getSource(), false); - } catch (RecipientFormattingException e) { - Log.w("MessageNotifier", e); - recipients = new Recipients(Recipient.getUnknownRecipient(context)); - } - - Recipient recipient = recipients.getPrimaryRecipient(); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients); - SpannableString body = new SpannableString(context.getString(R.string.MessageNotifier_encrypted_message)); + Recipients recipients = RecipientFactory.getRecipientsFromString(context, envelope.getSource(), false); + Recipient recipient = recipients.getPrimaryRecipient(); + long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients); + SpannableString body = new SpannableString(context.getString(R.string.MessageNotifier_encrypted_message)); body.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, body.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); notificationState.addNotification(new NotificationItem(recipient, recipients, null, threadId, body, null)); diff --git a/src/org/thoughtcrime/securesms/push/SecurityEventListener.java b/src/org/thoughtcrime/securesms/push/SecurityEventListener.java index 495024ba5..309c44267 100644 --- a/src/org/thoughtcrime/securesms/push/SecurityEventListener.java +++ b/src/org/thoughtcrime/securesms/push/SecurityEventListener.java @@ -7,6 +7,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.Recipients; import org.whispersystems.textsecure.api.TextSecureMessageSender; +import org.whispersystems.textsecure.api.push.TextSecureAddress; public class SecurityEventListener implements TextSecureMessageSender.EventListener { @@ -19,8 +20,8 @@ public class SecurityEventListener implements TextSecureMessageSender.EventListe } @Override - public void onSecurityEvent(long recipientId) { - Recipients recipients = RecipientFactory.getRecipientsForIds(context, new long[]{recipientId}, false); + public void onSecurityEvent(TextSecureAddress textSecureAddress) { + Recipients recipients = RecipientFactory.getRecipientsFromString(context, textSecureAddress.getNumber(), false); long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients); SecurityEvent.broadcastSecurityUpdateEvent(context, threadId); diff --git a/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java b/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java index 765811fac..d985b1902 100644 --- a/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java +++ b/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java @@ -17,13 +17,13 @@ package org.thoughtcrime.securesms.recipients; import android.content.Context; +import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Log; import org.thoughtcrime.securesms.contacts.ContactPhotoFactory; import org.thoughtcrime.securesms.database.CanonicalAddressDatabase; -import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.StringTokenizer; @@ -67,14 +67,8 @@ public class RecipientFactory { return provider.getRecipient(context, recipientId, asynchronous); } - public static Recipients getRecipientsFromString(Context context, String rawText, boolean asynchronous) - throws RecipientFormattingException - { - if (rawText == null) { - throw new RecipientFormattingException("Null recipient string specified"); - } - - List results = new LinkedList(); + public static Recipients getRecipientsFromString(Context context, @NonNull String rawText, boolean asynchronous) { + List results = new LinkedList<>(); StringTokenizer tokenizer = new StringTokenizer(rawText, ","); while (tokenizer.hasMoreTokens()) { diff --git a/src/org/thoughtcrime/securesms/service/RegistrationService.java b/src/org/thoughtcrime/securesms/service/RegistrationService.java index b4e53c6ae..b1fd67ee5 100644 --- a/src/org/thoughtcrime/securesms/service/RegistrationService.java +++ b/src/org/thoughtcrime/securesms/service/RegistrationService.java @@ -234,29 +234,25 @@ public class RegistrationService extends Service { throws IOException { setState(new RegistrationState(RegistrationState.STATE_GENERATING_KEYS, number)); - try { - Recipient self = RecipientFactory.getRecipientsFromString(this, number, false).getPrimaryRecipient(); - IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(this, masterSecret); - List records = PreKeyUtil.generatePreKeys(this, masterSecret); - PreKeyRecord lastResort = PreKeyUtil.generateLastResortKey(this, masterSecret); - SignedPreKeyRecord signedPreKey = PreKeyUtil.generateSignedPreKey(this, masterSecret, identityKey); - accountManager.setPreKeys(identityKey.getPublicKey(),lastResort, signedPreKey, records); + Recipient self = RecipientFactory.getRecipientsFromString(this, number, false).getPrimaryRecipient(); + IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(this, masterSecret); + List records = PreKeyUtil.generatePreKeys(this, masterSecret); + PreKeyRecord lastResort = PreKeyUtil.generateLastResortKey(this, masterSecret); + SignedPreKeyRecord signedPreKey = PreKeyUtil.generateSignedPreKey(this, masterSecret, identityKey); + accountManager.setPreKeys(identityKey.getPublicKey(),lastResort, signedPreKey, records); - setState(new RegistrationState(RegistrationState.STATE_GCM_REGISTERING, number)); + setState(new RegistrationState(RegistrationState.STATE_GCM_REGISTERING, number)); - String gcmRegistrationId = GoogleCloudMessaging.getInstance(this).register(GcmRefreshJob.REGISTRATION_ID); - accountManager.setGcmId(Optional.of(gcmRegistrationId)); + String gcmRegistrationId = GoogleCloudMessaging.getInstance(this).register(GcmRefreshJob.REGISTRATION_ID); + accountManager.setGcmId(Optional.of(gcmRegistrationId)); - TextSecurePreferences.setGcmRegistrationId(this, gcmRegistrationId); - TextSecurePreferences.setWebsocketRegistered(this, true); + TextSecurePreferences.setGcmRegistrationId(this, gcmRegistrationId); + TextSecurePreferences.setWebsocketRegistered(this, true); - DatabaseFactory.getIdentityDatabase(this).saveIdentity(masterSecret, self.getRecipientId(), identityKey.getPublicKey()); - DirectoryHelper.refreshDirectory(this, accountManager, number); + DatabaseFactory.getIdentityDatabase(this).saveIdentity(masterSecret, self.getRecipientId(), identityKey.getPublicKey()); + DirectoryHelper.refreshDirectory(this, accountManager, number); - DirectoryRefreshListener.schedule(this); - } catch (RecipientFormattingException e) { - throw new IOException(e); - } + DirectoryRefreshListener.schedule(this); } private synchronized String waitForChallenge() throws AccountVerificationTimeoutException { diff --git a/src/org/thoughtcrime/securesms/util/BitmapWorkerRunnable.java b/src/org/thoughtcrime/securesms/util/BitmapWorkerRunnable.java index c5bf9a121..ef45bfdf4 100644 --- a/src/org/thoughtcrime/securesms/util/BitmapWorkerRunnable.java +++ b/src/org/thoughtcrime/securesms/util/BitmapWorkerRunnable.java @@ -18,19 +18,15 @@ package org.thoughtcrime.securesms.util; import android.content.Context; -import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.util.Log; import android.widget.ImageView; import com.makeramen.RoundedDrawable; -import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientFactory; -import org.thoughtcrime.securesms.recipients.RecipientFormattingException; import java.lang.ref.WeakReference; @@ -59,28 +55,24 @@ public class BitmapWorkerRunnable implements Runnable { @Override public void run() { - try { - final Recipient recipient = RecipientFactory.getRecipientsFromString(context, number, false).getPrimaryRecipient(); - final Bitmap contactPhoto = recipient.getContactPhoto(); - if (defaultPhoto == contactPhoto) { - return; - } - if (recipient.getContactPhoto() != null) { - final ImageView imageView = imageViewReference.get(); - final TaggedFutureTask bitmapWorkerTask = AsyncDrawable.getBitmapWorkerTask(imageView); + final Recipient recipient = RecipientFactory.getRecipientsFromString(context, number, false).getPrimaryRecipient(); + final Bitmap contactPhoto = recipient.getContactPhoto(); + if (defaultPhoto == contactPhoto) { + return; + } + if (recipient.getContactPhoto() != null) { + final ImageView imageView = imageViewReference.get(); + final TaggedFutureTask bitmapWorkerTask = AsyncDrawable.getBitmapWorkerTask(imageView); - if (bitmapWorkerTask.getTag().equals(number) && imageView != null) { - final BitmapDrawable drawable = new BitmapDrawable(context.getResources(), recipient.getContactPhoto()); - imageView.post(new Runnable() { - @Override - public void run() { - imageView.setImageDrawable(drawable); - } - }); - } + if (bitmapWorkerTask.getTag().equals(number) && imageView != null) { + final BitmapDrawable drawable = new BitmapDrawable(context.getResources(), recipient.getContactPhoto()); + imageView.post(new Runnable() { + @Override + public void run() { + imageView.setImageDrawable(drawable); + } + }); } - } catch (RecipientFormattingException rfe) { - Log.w(TAG, "Couldn't get recipient from string", rfe); } }