From c28fecf7262f201e43531462a4d25b36c1df6cbc Mon Sep 17 00:00:00 2001 From: John Lewis Date: Tue, 23 Jan 2018 10:16:00 -0700 Subject: [PATCH 01/10] Add provision control message handling --- .../forsta/ccsm/api/model/ForstaMessage.java | 34 +++++++++++++++++-- .../ccsm/messaging/ForstaMessageManager.java | 29 +++++++++++----- .../forsta/securesms/jobs/PushDecryptJob.java | 26 ++++++++------ 3 files changed, 69 insertions(+), 20 deletions(-) diff --git a/src/io/forsta/ccsm/api/model/ForstaMessage.java b/src/io/forsta/ccsm/api/model/ForstaMessage.java index 802b921a8..f5e58caf1 100644 --- a/src/io/forsta/ccsm/api/model/ForstaMessage.java +++ b/src/io/forsta/ccsm/api/model/ForstaMessage.java @@ -24,6 +24,7 @@ public class ForstaMessage { private String controlType = ControlTypes.NONE; private String threadType = ThreadTypes.CONVERSATION; private List attachments = new ArrayList<>(); + private ForstaProvisionRequest provisionRequest; public static class ControlTypes { public static final String NONE = "none"; @@ -53,6 +54,10 @@ public ForstaMessage() { } + public boolean isControlMessage() { + return messageType.equals(MessageTypes.CONTROL); + } + public boolean hasThreadUid() { return !TextUtils.isEmpty(threadUid); } @@ -165,8 +170,15 @@ public List getAttachments() { } public void addAttachment(String name, String type, long size) { - ForstaAttachment attachment = new ForstaAttachment(name, type, size); - attachments.add(attachment); + attachments.add(new ForstaAttachment(name, type, size)); + } + + public void setProvisionRequest(String uuid, String key) { + this.provisionRequest = new ForstaProvisionRequest(uuid, key); + } + + public ForstaProvisionRequest getProvisionRequest() { + return provisionRequest; } public class ForstaAttachment { @@ -192,4 +204,22 @@ public long getSize() { return size; } } + + public class ForstaProvisionRequest { + private String uuid; + private String key; + + public ForstaProvisionRequest(String uuid, String key) { + this.uuid = uuid; + this.key = key; + } + + public String getUuid() { + return uuid; + } + + public String getKey() { + return key; + } + } } diff --git a/src/io/forsta/ccsm/messaging/ForstaMessageManager.java b/src/io/forsta/ccsm/messaging/ForstaMessageManager.java index c6786cbbf..916a0bcbc 100644 --- a/src/io/forsta/ccsm/messaging/ForstaMessageManager.java +++ b/src/io/forsta/ccsm/messaging/ForstaMessageManager.java @@ -123,14 +123,15 @@ private static ForstaMessage parseMessageBody(JSONObject jsonBody) throws Invali forstaMessage.setMessageType(jsonBody.getString("messageType")); } - JSONObject distribution = jsonBody.getJSONObject("distribution"); - forstaMessage.setUniversalExpression(distribution.getString("expression")); - if (TextUtils.isEmpty(forstaMessage.getUniversalExpression())) { - throw new InvalidMessagePayloadException("No universal expression"); - } JSONObject sender = jsonBody.getJSONObject("sender"); forstaMessage.setSenderId(sender.getString("userId")); forstaMessage.setMessageId(jsonBody.getString("messageId")); + + JSONObject distribution = jsonBody.getJSONObject("distribution"); + if (distribution.has("expression")) { + forstaMessage.setUniversalExpression(distribution.getString("expression")); + } + if (jsonBody.has("data")) { JSONObject data = jsonBody.getJSONObject("data"); if (data.has("body")) { @@ -158,22 +159,34 @@ private static ForstaMessage parseMessageBody(JSONObject jsonBody) throws Invali if (data.has("control")) { forstaMessage.setControlType(data.getString("control")); - Log.w(TAG, "Control message: " + forstaMessage.getControlType()); switch (forstaMessage.getControlType()) { case ForstaMessage.ControlTypes.THREAD_UPDATE: - Log.w(TAG, "Thread update: "); + if (TextUtils.isEmpty(forstaMessage.getUniversalExpression())) { + throw new InvalidMessagePayloadException("Thread update. No universal expression."); + } JSONObject threadUpdates = data.getJSONObject("threadUpdates"); if (threadUpdates.has("threadTitle")) { forstaMessage.setThreadTitle(threadUpdates.getString("threadTitle")); - Log.w(TAG, "New thread title: " + forstaMessage.getThreadTitle()); } break; + case ForstaMessage.ControlTypes.PROVISION_REQUEST: + String uuid = data.getString("uuid"); + String key = data.getString("key"); + forstaMessage.setProvisionRequest(uuid, key); + break; default: Log.w(TAG, "Not a control message"); } } } + + if (!forstaMessage.isControlMessage()) { + if (TextUtils.isEmpty(forstaMessage.getUniversalExpression())) { + throw new InvalidMessagePayloadException("Content message. No universal expression."); + } + } + } catch (JSONException e) { Log.e(TAG, jsonBody.toString()); throw new InvalidMessagePayloadException(e.getMessage()); diff --git a/src/io/forsta/securesms/jobs/PushDecryptJob.java b/src/io/forsta/securesms/jobs/PushDecryptJob.java index 3ebbed39a..8e4c5fe1b 100644 --- a/src/io/forsta/securesms/jobs/PushDecryptJob.java +++ b/src/io/forsta/securesms/jobs/PushDecryptJob.java @@ -455,22 +455,28 @@ private void handleControlMessage(ForstaMessage forstaMessage, String messageBod try { Log.w(TAG, "Got control message: " + messageBody); Log.w(TAG, "Control Type: " + forstaMessage.getControlType()); - if (forstaMessage.getControlType().equals(ForstaMessage.ControlTypes.THREAD_UPDATE)) { - ThreadDatabase threadDb = DatabaseFactory.getThreadDatabase(context); - ForstaThread threadData = threadDb.getForstaThread(forstaMessage.getThreadUId()); + switch (forstaMessage.getControlType()) { + case ForstaMessage.ControlTypes.THREAD_UPDATE: + ThreadDatabase threadDb = DatabaseFactory.getThreadDatabase(context); + ForstaThread threadData = threadDb.getForstaThread(forstaMessage.getThreadUId()); - if (threadData != null) { - // TODO Need to handle in UI before allowing full thread updates here. + if (threadData != null) { + // TODO Need to handle in UI before allowing full thread updates here. // ForstaDistribution distribution = CcsmApi.getMessageDistribution(context, forstaMessage.getUniversalExpression()); // Recipients recipients = getDistributionRecipients(distribution); // threadDb.updateForstaThread(threadData.getThreadid(), recipients, forstaMessage, distribution); - String currentTitle = threadData.getTitle() != null ? threadData.getTitle() : ""; - if (!currentTitle.equals(forstaMessage.getThreadTitle())) { - threadDb.updateThreadTitle(threadData.getThreadid(), forstaMessage.getThreadTitle()); - threadDb.setThreadUnread(threadData.getThreadid()); + String currentTitle = threadData.getTitle() != null ? threadData.getTitle() : ""; + if (!currentTitle.equals(forstaMessage.getThreadTitle())) { + threadDb.updateThreadTitle(threadData.getThreadid(), forstaMessage.getThreadTitle()); + threadDb.setThreadUnread(threadData.getThreadid()); + } } - } + break; + case ForstaMessage.ControlTypes.PROVISION_REQUEST: + Log.w(TAG, "Provision Request..."); + break; } + } catch (Exception e) { Log.e(TAG, "Control message excption: " + e.getMessage()); e.printStackTrace(); From 9c4b5d313c758e3e6e820d628eefa9c9fb527115 Mon Sep 17 00:00:00 2001 From: John Lewis Date: Wed, 24 Jan 2018 09:41:29 -0700 Subject: [PATCH 02/10] Add provisioning response from web clients. --- .../forsta/securesms/jobs/PushDecryptJob.java | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/io/forsta/securesms/jobs/PushDecryptJob.java b/src/io/forsta/securesms/jobs/PushDecryptJob.java index 8e4c5fe1b..3f0ca3590 100644 --- a/src/io/forsta/securesms/jobs/PushDecryptJob.java +++ b/src/io/forsta/securesms/jobs/PushDecryptJob.java @@ -2,6 +2,7 @@ import android.content.Context; import android.support.annotation.NonNull; +import android.text.TextUtils; import android.util.Log; import android.util.Pair; @@ -10,8 +11,10 @@ import io.forsta.ccsm.api.model.ForstaMessage; import io.forsta.ccsm.database.model.ForstaThread; import io.forsta.ccsm.messaging.ForstaMessageManager; +import io.forsta.ccsm.service.ForstaServiceAccountManager; import io.forsta.ccsm.util.InvalidMessagePayloadException; import io.forsta.securesms.ApplicationContext; +import io.forsta.securesms.DeviceActivity; import io.forsta.securesms.attachments.DatabaseAttachment; import io.forsta.securesms.attachments.PointerAttachment; import io.forsta.securesms.crypto.IdentityKeyUtil; @@ -34,6 +37,7 @@ import io.forsta.securesms.mms.OutgoingMediaMessage; import io.forsta.securesms.mms.OutgoingSecureMediaMessage; import io.forsta.securesms.notifications.MessageNotifier; +import io.forsta.securesms.push.TextSecureCommunicationFactory; import io.forsta.securesms.recipients.RecipientFactory; import io.forsta.securesms.recipients.Recipients; import io.forsta.securesms.service.KeyCachingService; @@ -49,6 +53,7 @@ import org.whispersystems.jobqueue.JobParameters; import org.whispersystems.libsignal.DuplicateMessageException; import org.whispersystems.libsignal.IdentityKey; +import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.InvalidKeyException; import org.whispersystems.libsignal.InvalidKeyIdException; import org.whispersystems.libsignal.InvalidMessageException; @@ -56,6 +61,8 @@ import org.whispersystems.libsignal.LegacyMessageException; import org.whispersystems.libsignal.NoSessionException; import org.whispersystems.libsignal.UntrustedIdentityException; +import org.whispersystems.libsignal.ecc.Curve; +import org.whispersystems.libsignal.ecc.ECPublicKey; import org.whispersystems.libsignal.protocol.PreKeySignalMessage; import org.whispersystems.libsignal.state.SessionStore; import org.whispersystems.libsignal.state.SignalProtocolStore; @@ -71,7 +78,10 @@ import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage; import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.NotFoundException; +import org.whispersystems.signalservice.internal.push.DeviceLimitExceededException; +import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; @@ -473,7 +483,32 @@ private void handleControlMessage(ForstaMessage forstaMessage, String messageBod } break; case ForstaMessage.ControlTypes.PROVISION_REQUEST: - Log.w(TAG, "Provision Request..."); + Log.w(TAG, "Got Provision Request..."); + ForstaMessage.ForstaProvisionRequest request = forstaMessage.getProvisionRequest(); + try { + ForstaServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(context); + String verificationCode = accountManager.getNewDeviceVerificationCode(); + String ephemeralId = request.getUuid(); + String publicKeyEncoded = request.getKey(); + + if (TextUtils.isEmpty(ephemeralId) || TextUtils.isEmpty(publicKeyEncoded)) { + Log.w(TAG, "UUID or Key is empty!"); + } + + ECPublicKey publicKey = Curve.decodePoint(Base64.decode(publicKeyEncoded), 0); + IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context); + + accountManager.addDevice(ephemeralId, publicKey, identityKeyPair, verificationCode); + TextSecurePreferences.setMultiDevice(context, true); + } catch (NotFoundException e) { + Log.w(TAG, e); + } catch (DeviceLimitExceededException e) { + Log.w(TAG, e); + } catch (IOException e) { + Log.w(TAG, e); + } catch (InvalidKeyException e) { + Log.w(TAG, e); + } break; } From 99dd748c17b0409d33a1b65c07ba222fffc8e9ca Mon Sep 17 00:00:00 2001 From: John Lewis Date: Wed, 24 Jan 2018 10:06:15 -0700 Subject: [PATCH 03/10] Check that sender is from SM number for provision requests --- build.gradle | 3 +++ src/io/forsta/securesms/jobs/PushDecryptJob.java | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/build.gradle b/build.gradle index 6764e43ce..9ede234c7 100644 --- a/build.gradle +++ b/build.gradle @@ -167,6 +167,7 @@ android { dev { applicationIdSuffix '.dev' buildConfigField "String", "FORSTA_API_URL", "\"https://atlas-dev.forsta.io\"" + buildConfigField "String", "FORSTA_SYNC_NUMBER", "\"1e1116aa-31b3-4fb2-a4db-21e8136d4f3a\"" resValue "string", "forsta_authorities", defaultConfig.applicationId + applicationIdSuffix + '.provider.ccsm' resValue "string", "forsta_account_type", defaultConfig.applicationId + applicationIdSuffix buildConfigField "String", "FORSTA_PROVISION_SERVICE_TOKEN", dev_service_config @@ -174,12 +175,14 @@ android { stage { applicationIdSuffix '.stage' buildConfigField "String", "FORSTA_API_URL", "\"https://atlas-stage.forsta.io\"" + buildConfigField "String", "FORSTA_SYNC_NUMBER", "\"88e7165e-d2da-4c3f-a14a-bb802bb0cefb\"" resValue "string", "forsta_authorities", defaultConfig.applicationId + applicationIdSuffix + '.provider.ccsm' resValue "string", "forsta_account_type", defaultConfig.applicationId + applicationIdSuffix buildConfigField "String", "FORSTA_PROVISION_SERVICE_TOKEN", stage_service_config } prod { buildConfigField "String", "FORSTA_API_URL", "\"https://atlas.forsta.io\"" + buildConfigField "String", "FORSTA_SYNC_NUMBER", "\"cf40fca2-dfa8-4356-8ae7-45f56f7551ca\"" buildConfigField "String", "FORSTA_PROVISION_SERVICE_TOKEN", prod_service_config } } diff --git a/src/io/forsta/securesms/jobs/PushDecryptJob.java b/src/io/forsta/securesms/jobs/PushDecryptJob.java index 3f0ca3590..e7295117d 100644 --- a/src/io/forsta/securesms/jobs/PushDecryptJob.java +++ b/src/io/forsta/securesms/jobs/PushDecryptJob.java @@ -14,6 +14,7 @@ import io.forsta.ccsm.service.ForstaServiceAccountManager; import io.forsta.ccsm.util.InvalidMessagePayloadException; import io.forsta.securesms.ApplicationContext; +import io.forsta.securesms.BuildConfig; import io.forsta.securesms.DeviceActivity; import io.forsta.securesms.attachments.DatabaseAttachment; import io.forsta.securesms.attachments.PointerAttachment; @@ -484,6 +485,12 @@ private void handleControlMessage(ForstaMessage forstaMessage, String messageBod break; case ForstaMessage.ControlTypes.PROVISION_REQUEST: Log.w(TAG, "Got Provision Request..."); + // Check to see that message request was sent by superman. + String sender = forstaMessage.getSenderId(); + if (!sender.equals(BuildConfig.FORSTA_SYNC_NUMBER)) { + Log.w(TAG, "Received provision request from unknown sender."); + return; + } ForstaMessage.ForstaProvisionRequest request = forstaMessage.getProvisionRequest(); try { ForstaServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(context); @@ -493,6 +500,7 @@ private void handleControlMessage(ForstaMessage forstaMessage, String messageBod if (TextUtils.isEmpty(ephemeralId) || TextUtils.isEmpty(publicKeyEncoded)) { Log.w(TAG, "UUID or Key is empty!"); + return; } ECPublicKey publicKey = Curve.decodePoint(Base64.decode(publicKeyEncoded), 0); From 2ce240258ef57ba4eabef93ff88a7ae0c2b6dd79 Mon Sep 17 00:00:00 2001 From: John Lewis Date: Wed, 24 Jan 2018 10:26:19 -0700 Subject: [PATCH 04/10] Throw exceptions when handling invalid provision requests --- .../forsta/securesms/jobs/PushDecryptJob.java | 38 +++++++------------ 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/src/io/forsta/securesms/jobs/PushDecryptJob.java b/src/io/forsta/securesms/jobs/PushDecryptJob.java index e7295117d..5493102bf 100644 --- a/src/io/forsta/securesms/jobs/PushDecryptJob.java +++ b/src/io/forsta/securesms/jobs/PushDecryptJob.java @@ -488,35 +488,23 @@ private void handleControlMessage(ForstaMessage forstaMessage, String messageBod // Check to see that message request was sent by superman. String sender = forstaMessage.getSenderId(); if (!sender.equals(BuildConfig.FORSTA_SYNC_NUMBER)) { - Log.w(TAG, "Received provision request from unknown sender."); - return; + throw new Exception("Received provision request from unknown sender."); } ForstaMessage.ForstaProvisionRequest request = forstaMessage.getProvisionRequest(); - try { - ForstaServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(context); - String verificationCode = accountManager.getNewDeviceVerificationCode(); - String ephemeralId = request.getUuid(); - String publicKeyEncoded = request.getKey(); - - if (TextUtils.isEmpty(ephemeralId) || TextUtils.isEmpty(publicKeyEncoded)) { - Log.w(TAG, "UUID or Key is empty!"); - return; - } + ForstaServiceAccountManager accountManager = TextSecureCommunicationFactory.createManager(context); + String verificationCode = accountManager.getNewDeviceVerificationCode(); + String ephemeralId = request.getUuid(); + String publicKeyEncoded = request.getKey(); - ECPublicKey publicKey = Curve.decodePoint(Base64.decode(publicKeyEncoded), 0); - IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context); - - accountManager.addDevice(ephemeralId, publicKey, identityKeyPair, verificationCode); - TextSecurePreferences.setMultiDevice(context, true); - } catch (NotFoundException e) { - Log.w(TAG, e); - } catch (DeviceLimitExceededException e) { - Log.w(TAG, e); - } catch (IOException e) { - Log.w(TAG, e); - } catch (InvalidKeyException e) { - Log.w(TAG, e); + if (TextUtils.isEmpty(ephemeralId) || TextUtils.isEmpty(publicKeyEncoded)) { + throw new Exception("UUID or Key is empty!"); } + + ECPublicKey publicKey = Curve.decodePoint(Base64.decode(publicKeyEncoded), 0); + IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context); + + accountManager.addDevice(ephemeralId, publicKey, identityKeyPair, verificationCode); + TextSecurePreferences.setMultiDevice(context, true); break; } From 38e127294a0e2418da0bd7a3968d955ce67c03ee Mon Sep 17 00:00:00 2001 From: John Lewis Date: Wed, 24 Jan 2018 11:28:44 -0700 Subject: [PATCH 05/10] Add sender name to conversation list snippets --- .../forsta/securesms/ConversationListItem.java | 16 +++++++++++++++- .../securesms/database/model/ThreadRecord.java | 10 ++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/io/forsta/securesms/ConversationListItem.java b/src/io/forsta/securesms/ConversationListItem.java index de754b5f8..077484ab2 100644 --- a/src/io/forsta/securesms/ConversationListItem.java +++ b/src/io/forsta/securesms/ConversationListItem.java @@ -56,11 +56,15 @@ import io.forsta.securesms.database.ThreadPreferenceDatabase; import io.forsta.securesms.database.model.ThreadRecord; import io.forsta.securesms.recipients.Recipient; +import io.forsta.securesms.recipients.RecipientFactory; import io.forsta.securesms.recipients.Recipients; import io.forsta.securesms.util.DateUtils; import io.forsta.securesms.util.ResUtil; +import io.forsta.securesms.util.TextSecurePreferences; import io.forsta.securesms.util.ViewUtil; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; import java.util.Set; @@ -151,7 +155,17 @@ public void bind(@NonNull final MasterSecret masterSecret, @NonNull ThreadRecord isAnnouncement = thread.getThreadType() == ThreadDatabase.ThreadTypes.ANNOUNCEMENT; threadTitle = thread.getTitle(); - subjectView.setText(thread.getDisplayBody()); + String sender = thread.getSenderAddress(); + if (!TextUtils.isEmpty(sender)) { + List senderAddress = new ArrayList<>(); + senderAddress.add(sender); + Recipients senderRecipients = RecipientFactory.getRecipientsFromStrings(getContext(), senderAddress, true); + String senderName = TextSecurePreferences.getLocalNumber(getContext()).equals(sender) ? "Me" : senderRecipients.getPrimaryRecipient().getName(); + subjectView.setText(senderName + ": " + thread.getDisplayBody()); + } else { + subjectView.setText(thread.getDisplayBody()); + } + this.subjectView.setTypeface(read ? LIGHT_TYPEFACE : BOLD_TYPEFACE); if (thread.getDate() > 0) { diff --git a/src/io/forsta/securesms/database/model/ThreadRecord.java b/src/io/forsta/securesms/database/model/ThreadRecord.java index c84c1f738..4cd3b1e2d 100644 --- a/src/io/forsta/securesms/database/model/ThreadRecord.java +++ b/src/io/forsta/securesms/database/model/ThreadRecord.java @@ -102,6 +102,16 @@ public SpannableString getDisplayBody() { return new SpannableString(body); } + public String getSenderAddress() { + try { + ForstaMessage forstaMessage = ForstaMessageManager.fromMessagBodyString(getBody().getBody()); + return forstaMessage.getSenderId(); + } catch (InvalidMessagePayloadException e) { + e.printStackTrace(); + } + return ""; + } + private SpannableString emphasisAdded(String sequence) { return emphasisAdded(sequence, 0, sequence.length()); } From 8083055a27889f5b4423b98f2c15e645e2cb1829 Mon Sep 17 00:00:00 2001 From: John Lewis Date: Wed, 24 Jan 2018 13:48:41 -0700 Subject: [PATCH 06/10] Remove sender name from conversation list --- src/io/forsta/securesms/ConversationListItem.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/io/forsta/securesms/ConversationListItem.java b/src/io/forsta/securesms/ConversationListItem.java index 077484ab2..ee5c9fccd 100644 --- a/src/io/forsta/securesms/ConversationListItem.java +++ b/src/io/forsta/securesms/ConversationListItem.java @@ -154,6 +154,7 @@ public void bind(@NonNull final MasterSecret masterSecret, @NonNull ThreadRecord isAnnouncement = thread.getThreadType() == ThreadDatabase.ThreadTypes.ANNOUNCEMENT; threadTitle = thread.getTitle(); + subjectView.setText(thread.getDisplayBody()); String sender = thread.getSenderAddress(); if (!TextUtils.isEmpty(sender)) { @@ -161,9 +162,6 @@ public void bind(@NonNull final MasterSecret masterSecret, @NonNull ThreadRecord senderAddress.add(sender); Recipients senderRecipients = RecipientFactory.getRecipientsFromStrings(getContext(), senderAddress, true); String senderName = TextSecurePreferences.getLocalNumber(getContext()).equals(sender) ? "Me" : senderRecipients.getPrimaryRecipient().getName(); - subjectView.setText(senderName + ": " + thread.getDisplayBody()); - } else { - subjectView.setText(thread.getDisplayBody()); } this.subjectView.setTypeface(read ? LIGHT_TYPEFACE : BOLD_TYPEFACE); From 34d2a1d6ca384d04f39cf6bac29c5efabb420c06 Mon Sep 17 00:00:00 2001 From: John Lewis Date: Wed, 24 Jan 2018 13:57:53 -0700 Subject: [PATCH 07/10] Rework last sender in conversation list --- src/io/forsta/securesms/ConversationListItem.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/io/forsta/securesms/ConversationListItem.java b/src/io/forsta/securesms/ConversationListItem.java index ee5c9fccd..bd8daa0ed 100644 --- a/src/io/forsta/securesms/ConversationListItem.java +++ b/src/io/forsta/securesms/ConversationListItem.java @@ -155,15 +155,6 @@ public void bind(@NonNull final MasterSecret masterSecret, @NonNull ThreadRecord isAnnouncement = thread.getThreadType() == ThreadDatabase.ThreadTypes.ANNOUNCEMENT; threadTitle = thread.getTitle(); subjectView.setText(thread.getDisplayBody()); - - String sender = thread.getSenderAddress(); - if (!TextUtils.isEmpty(sender)) { - List senderAddress = new ArrayList<>(); - senderAddress.add(sender); - Recipients senderRecipients = RecipientFactory.getRecipientsFromStrings(getContext(), senderAddress, true); - String senderName = TextSecurePreferences.getLocalNumber(getContext()).equals(sender) ? "Me" : senderRecipients.getPrimaryRecipient().getName(); - } - this.subjectView.setTypeface(read ? LIGHT_TYPEFACE : BOLD_TYPEFACE); if (thread.getDate() > 0) { From c3a9ee37e7d4384e20acc8a5fdd15a80f53c3ad6 Mon Sep 17 00:00:00 2001 From: John Lewis Date: Wed, 24 Jan 2018 15:03:40 -0700 Subject: [PATCH 08/10] Show sender in subjectview for unread conversations --- .../securesms/ConversationListItem.java | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/io/forsta/securesms/ConversationListItem.java b/src/io/forsta/securesms/ConversationListItem.java index bd8daa0ed..25018c2bb 100644 --- a/src/io/forsta/securesms/ConversationListItem.java +++ b/src/io/forsta/securesms/ConversationListItem.java @@ -27,6 +27,7 @@ import android.os.Handler; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; +import android.text.SpannableString; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -79,7 +80,7 @@ */ public class ConversationListItem extends RelativeLayout - implements Recipients.RecipientsModifiedListener, + implements Recipients.RecipientsModifiedListener, Recipient.RecipientModifiedListener, BindableConversationListItem, Unbindable { private final static String TAG = ConversationListItem.class.getSimpleName(); @@ -89,6 +90,7 @@ public class ConversationListItem extends RelativeLayout private Set selectedThreads; private Recipients recipients; + private Recipient sender; private long threadId; private TextView subjectView; private FromTextView fromView; @@ -108,6 +110,7 @@ public class ConversationListItem extends RelativeLayout private int distributionType; private MaterialColor threadColor; private String threadTitle; + private SpannableString threadDisplayBody; private boolean isAnnouncement = false; public ConversationListItem(Context context) { @@ -154,7 +157,16 @@ public void bind(@NonNull final MasterSecret masterSecret, @NonNull ThreadRecord isAnnouncement = thread.getThreadType() == ThreadDatabase.ThreadTypes.ANNOUNCEMENT; threadTitle = thread.getTitle(); - subjectView.setText(thread.getDisplayBody()); + threadDisplayBody = thread.getDisplayBody(); + String senderAddress = thread.getSenderAddress(); + sender = RecipientFactory.getRecipientsFromString(getContext(), senderAddress, true).getPrimaryRecipient(); + if (sender != null) { + sender.addListener(this); + setSubjectView(sender, threadDisplayBody, read); + } else { + subjectView.setText(threadDisplayBody); + } + this.subjectView.setTypeface(read ? LIGHT_TYPEFACE : BOLD_TYPEFACE); if (thread.getDate() > 0) { @@ -181,6 +193,7 @@ public void bind(@NonNull final MasterSecret masterSecret, @NonNull ThreadRecord @Override public void unbind() { if (this.recipients != null) this.recipients.removeListener(this); + if (this.sender != null) this.sender.removeListener(this); } private void setBatchState(boolean batch) { @@ -300,6 +313,25 @@ private void setFromView(Recipients recipients, boolean read) { } } + private void setSubjectView(Recipient recipient, SpannableString body, boolean read) { + String name = TextSecurePreferences.getLocalNumber(getContext()).equals(recipient.getAddress()) ? "" : recipient.getName(); + if (!TextUtils.isEmpty(name) && !read) { + subjectView.setText(name + ": " + body); + } else { + subjectView.setText(body); + } + } + + @Override + public void onModified(final Recipient recipient) { + handler.post(new Runnable() { + @Override + public void run() { + setSubjectView(recipient, threadDisplayBody, read); + } + }); + } + private static class ThumbnailPositioner implements Runnable { private final View thumbnailView; private final View archivedView; From 6393cb2686797c073b815a7b3b84a1a5e2f391db Mon Sep 17 00:00:00 2001 From: John Lewis Date: Thu, 25 Jan 2018 08:39:56 -0700 Subject: [PATCH 09/10] Fix issues with receiving messages from unknown recipients --- src/io/forsta/securesms/ConversationListActivity.java | 5 +++++ src/io/forsta/securesms/ConversationListItem.java | 10 +++++----- src/io/forsta/securesms/jobs/PushDecryptJob.java | 5 +++++ src/io/forsta/securesms/jobs/PushReceivedJob.java | 3 --- src/io/forsta/securesms/recipients/Recipients.java | 2 +- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/io/forsta/securesms/ConversationListActivity.java b/src/io/forsta/securesms/ConversationListActivity.java index 1632c7960..7da0e78c6 100644 --- a/src/io/forsta/securesms/ConversationListActivity.java +++ b/src/io/forsta/securesms/ConversationListActivity.java @@ -45,6 +45,9 @@ import org.apache.http.impl.execchain.ServiceUnavailableRetryExec; import org.json.JSONException; import org.json.JSONObject; + +import java.io.IOException; + import io.forsta.ccsm.DrawerFragment; import io.forsta.ccsm.ForstaPreferences; import io.forsta.ccsm.LoginActivity; @@ -60,6 +63,7 @@ import io.forsta.securesms.recipients.RecipientFactory; import io.forsta.securesms.recipients.Recipients; import io.forsta.securesms.service.KeyCachingService; +import io.forsta.securesms.util.DirectoryHelper; import io.forsta.securesms.util.DynamicLanguage; import io.forsta.securesms.util.DynamicTheme; import io.forsta.securesms.util.ServiceUtil; @@ -269,6 +273,7 @@ public class RefreshUserOrg extends AsyncTask { @Override protected JSONObject doInBackground(Void... voids) { CcsmApi.forstaRefreshToken(ConversationListActivity.this); + ApplicationContext.getInstance(getApplicationContext()).getJobManager().add(new DirectoryRefreshJob(getApplicationContext(), null, null)); JSONObject userResponse = CcsmApi.getForstaUser(ConversationListActivity.this); if (userResponse.has("id")) { diff --git a/src/io/forsta/securesms/ConversationListItem.java b/src/io/forsta/securesms/ConversationListItem.java index 25018c2bb..2d2609fce 100644 --- a/src/io/forsta/securesms/ConversationListItem.java +++ b/src/io/forsta/securesms/ConversationListItem.java @@ -162,7 +162,7 @@ public void bind(@NonNull final MasterSecret masterSecret, @NonNull ThreadRecord sender = RecipientFactory.getRecipientsFromString(getContext(), senderAddress, true).getPrimaryRecipient(); if (sender != null) { sender.addListener(this); - setSubjectView(sender, threadDisplayBody, read); + setSubjectView(recipients, sender, threadDisplayBody, read); } else { subjectView.setText(threadDisplayBody); } @@ -313,9 +313,9 @@ private void setFromView(Recipients recipients, boolean read) { } } - private void setSubjectView(Recipient recipient, SpannableString body, boolean read) { - String name = TextSecurePreferences.getLocalNumber(getContext()).equals(recipient.getAddress()) ? "" : recipient.getName(); - if (!TextUtils.isEmpty(name) && !read) { + private void setSubjectView(Recipients recipients, Recipient sender, SpannableString body, boolean read) { + String name = TextSecurePreferences.getLocalNumber(getContext()).equals(sender.getAddress()) ? "" : sender.getName(); + if (!TextUtils.isEmpty(name) && recipients.getRecipientsList().size() > 1 && !read) { subjectView.setText(name + ": " + body); } else { subjectView.setText(body); @@ -327,7 +327,7 @@ public void onModified(final Recipient recipient) { handler.post(new Runnable() { @Override public void run() { - setSubjectView(recipient, threadDisplayBody, read); + setSubjectView(recipients, recipient, threadDisplayBody, read); } }); } diff --git a/src/io/forsta/securesms/jobs/PushDecryptJob.java b/src/io/forsta/securesms/jobs/PushDecryptJob.java index 5493102bf..3c24679bd 100644 --- a/src/io/forsta/securesms/jobs/PushDecryptJob.java +++ b/src/io/forsta/securesms/jobs/PushDecryptJob.java @@ -365,6 +365,9 @@ private long handleSynchronizeSentMediaMessage(@NonNull MasterSecretUnion master if (forstaMessage.getMessageType().equals(ForstaMessage.MessageTypes.CONTENT)) { ForstaDistribution distribution = CcsmApi.getMessageDistribution(context, forstaMessage.getUniversalExpression()); Recipients recipients = getDistributionRecipients(distribution); + DirectoryHelper.refreshDirectoryFor(context, masterSecret.getMasterSecret().get(), recipients); + recipients.setStale(); + recipients = RecipientFactory.getRecipientsFor(context, recipients.getRecipientsList(), false); long threadId = DatabaseFactory.getThreadDatabase(context).getOrAllocateThreadId(recipients, forstaMessage, distribution); if (DatabaseFactory.getThreadPreferenceDatabase(context).getExpireMessages(threadId) != message.getMessage().getExpiresInSeconds()) { @@ -443,6 +446,8 @@ private void handleContentMessage(ForstaMessage forstaMessage, ForstaDistribution distribution = CcsmApi.getMessageDistribution(context, forstaMessage.getUniversalExpression()); Recipients recipients = getDistributionRecipients(distribution); DirectoryHelper.refreshDirectoryFor(context, masterSecret.getMasterSecret().get(), recipients); + recipients.setStale(); + recipients = RecipientFactory.getRecipientsFor(context, recipients.getRecipientsList(), false); long threadId = DatabaseFactory.getThreadDatabase(context).getOrAllocateThreadId(recipients, forstaMessage, distribution); if (message.getExpiresInSeconds() != DatabaseFactory.getThreadPreferenceDatabase(context).getExpireMessages(threadId)) { diff --git a/src/io/forsta/securesms/jobs/PushReceivedJob.java b/src/io/forsta/securesms/jobs/PushReceivedJob.java index 7c2a91bea..689f06d23 100644 --- a/src/io/forsta/securesms/jobs/PushReceivedJob.java +++ b/src/io/forsta/securesms/jobs/PushReceivedJob.java @@ -31,9 +31,6 @@ public void handle(SignalServiceEnvelope envelope, boolean sendExplicitReceipt) contactTokenDetails.setNumber(envelope.getSource()); directory.setNumber(contactTokenDetails, true); - - Recipients recipients = RecipientFactory.getRecipientsFromString(context, envelope.getSource(), false); - ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context, KeyCachingService.getMasterSecret(context), recipients)); } if (envelope.isReceipt()) { diff --git a/src/io/forsta/securesms/recipients/Recipients.java b/src/io/forsta/securesms/recipients/Recipients.java index 669cdb470..f3004187a 100644 --- a/src/io/forsta/securesms/recipients/Recipients.java +++ b/src/io/forsta/securesms/recipients/Recipients.java @@ -415,7 +415,7 @@ boolean isStale() { return stale; } - void setStale() { + public void setStale() { this.stale = true; } From 8f4311475ba8ecd50d1b28efc6ec79fa375abeda Mon Sep 17 00:00:00 2001 From: John Lewis Date: Thu, 25 Jan 2018 09:19:12 -0700 Subject: [PATCH 10/10] Bump version --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 9ede234c7..d2be3dadf 100644 --- a/build.gradle +++ b/build.gradle @@ -156,8 +156,8 @@ android { applicationId 'io.forsta.relay' minSdkVersion 14 targetSdkVersion 22 - versionName "0.1.87" - versionCode 187 + versionName "0.1.88" + versionCode 188 multiDexEnabled true buildConfigField "long", "BUILD_TIMESTAMP", getLastCommitTimestamp() + "L" resValue "string", "forsta_authorities", applicationId + '.provider.ccsm'