mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00:00
WIP: clean up signal protocols
This commit is contained in:
parent
13c2995746
commit
958ec690f1
@ -76,7 +76,6 @@ import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
|||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation;
|
|
||||||
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
|
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
|
||||||
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
||||||
@ -84,7 +83,6 @@ import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
|||||||
import org.thoughtcrime.securesms.notifications.OptimizedMessageNotifier;
|
import org.thoughtcrime.securesms.notifications.OptimizedMessageNotifier;
|
||||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
|
||||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||||
import org.thoughtcrime.securesms.service.IncomingMessageObserver;
|
import org.thoughtcrime.securesms.service.IncomingMessageObserver;
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
@ -107,8 +105,7 @@ import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI;
|
|||||||
import org.session.libsignal.service.loki.api.shelved.p2p.LokiP2PAPI;
|
import org.session.libsignal.service.loki.api.shelved.p2p.LokiP2PAPI;
|
||||||
import org.session.libsignal.service.loki.api.shelved.p2p.LokiP2PAPIDelegate;
|
import org.session.libsignal.service.loki.api.shelved.p2p.LokiP2PAPIDelegate;
|
||||||
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol;
|
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol;
|
||||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager;
|
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager;
|
||||||
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -136,7 +133,6 @@ import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
|
|||||||
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate {
|
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate {
|
||||||
|
|
||||||
private static final String TAG = ApplicationContext.class.getSimpleName();
|
private static final String TAG = ApplicationContext.class.getSimpleName();
|
||||||
private final static int OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10 MB
|
|
||||||
|
|
||||||
private ExpiringMessageManager expiringMessageManager;
|
private ExpiringMessageManager expiringMessageManager;
|
||||||
private TypingStatusRepository typingStatusRepository;
|
private TypingStatusRepository typingStatusRepository;
|
||||||
@ -144,7 +140,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
private JobManager jobManager;
|
private JobManager jobManager;
|
||||||
private ReadReceiptManager readReceiptManager;
|
private ReadReceiptManager readReceiptManager;
|
||||||
private ProfileManager profileManager;
|
private ProfileManager profileManager;
|
||||||
private IncomingMessageObserver incomingMessageObserver;
|
|
||||||
private ObjectGraph objectGraph;
|
private ObjectGraph objectGraph;
|
||||||
private PersistentLogger persistentLogger;
|
private PersistentLogger persistentLogger;
|
||||||
|
|
||||||
@ -182,7 +177,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(this);
|
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(this);
|
||||||
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
||||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||||
SessionResetImplementation sessionResetImpl = new SessionResetImplementation(this);
|
|
||||||
MessagingConfiguration.Companion.configure(this,
|
MessagingConfiguration.Companion.configure(this,
|
||||||
DatabaseFactory.getStorage(this),
|
DatabaseFactory.getStorage(this),
|
||||||
DatabaseFactory.getAttachmentProvider(this),
|
DatabaseFactory.getAttachmentProvider(this),
|
||||||
@ -191,7 +185,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||||
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||||
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
||||||
SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
|
||||||
}
|
}
|
||||||
setUpP2PAPIIfNeeded();
|
setUpP2PAPIIfNeeded();
|
||||||
PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG);
|
PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG);
|
||||||
@ -206,7 +199,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
UiModeUtilities.setupUiModeToUserSelected(this);
|
UiModeUtilities.setupUiModeToUserSelected(this);
|
||||||
// ========
|
// ========
|
||||||
initializeJobManager();
|
initializeJobManager();
|
||||||
initializeMessageRetrieval();
|
|
||||||
initializeExpiringMessageManager();
|
initializeExpiringMessageManager();
|
||||||
initializeTypingStatusRepository();
|
initializeTypingStatusRepository();
|
||||||
initializeTypingStatusSender();
|
initializeTypingStatusSender();
|
||||||
@ -347,10 +339,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initializeMessageRetrieval() {
|
|
||||||
this.incomingMessageObserver = new IncomingMessageObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeDependencyInjection() {
|
private void initializeDependencyInjection() {
|
||||||
communicationModule = new SignalCommunicationModule(this, new SignalServiceNetworkAccess(this));
|
communicationModule = new SignalCommunicationModule(this, new SignalServiceNetworkAccess(this));
|
||||||
this.objectGraph = ObjectGraph.create(communicationModule);
|
this.objectGraph = ObjectGraph.create(communicationModule);
|
||||||
|
@ -90,9 +90,8 @@ import org.session.libsession.utilities.MediaTypes;
|
|||||||
import org.session.libsignal.libsignal.InvalidMessageException;
|
import org.session.libsignal.libsignal.InvalidMessageException;
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
|
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
|
||||||
import org.session.libsignal.service.loki.protocol.mentions.Mention;
|
import org.session.libsignal.service.loki.utilities.mentions.Mention;
|
||||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager;
|
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager;
|
||||||
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol;
|
|
||||||
import org.session.libsignal.service.loki.utilities.HexEncodingKt;
|
import org.session.libsignal.service.loki.utilities.HexEncodingKt;
|
||||||
import org.session.libsignal.service.loki.utilities.PublicKeyValidation;
|
import org.session.libsignal.service.loki.utilities.PublicKeyValidation;
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
@ -144,7 +143,6 @@ import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
|||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabaseDelegate;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabaseDelegate;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2;
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
|
||||||
import org.thoughtcrime.securesms.loki.utilities.GeneralUtilitiesKt;
|
import org.thoughtcrime.securesms.loki.utilities.GeneralUtilitiesKt;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities;
|
||||||
@ -404,7 +402,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
});
|
});
|
||||||
|
|
||||||
sessionRestoreBannerView.setOnRestore(() -> {
|
sessionRestoreBannerView.setOnRestore(() -> {
|
||||||
SessionManagementProtocol.startSessionReset(this, recipient.getAddress().serialize());
|
|
||||||
updateSessionRestoreBanner();
|
updateSessionRestoreBanner();
|
||||||
return Unit.INSTANCE;
|
return Unit.INSTANCE;
|
||||||
});
|
});
|
||||||
@ -2003,7 +2000,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
Log.w(TAG, ex);
|
Log.w(TAG, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messageStatus == null && !isGroupConversation() && !SessionMetaProtocol.shared.isNoteToSelf(recipient.getAddress().serialize())) {
|
if (messageStatus == null && !isGroupConversation() && !(TextSecurePreferences.getLocalNumber(this).equals(recipient.getAddress().serialize()))) {
|
||||||
messageStatus = "calculatingPoW";
|
messageStatus = "calculatingPoW";
|
||||||
updateSubtitleTextView();
|
updateSubtitleTextView();
|
||||||
updateMessageStatusProgressBar();
|
updateMessageStatusProgressBar();
|
||||||
@ -2680,7 +2677,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleMessageStatusChanged(String newMessageStatus, long timestamp) {
|
private void handleMessageStatusChanged(String newMessageStatus, long timestamp) {
|
||||||
if (timestamp == 0 || SessionMetaProtocol.shared.isNoteToSelf(recipient.getAddress().serialize()) ) { return; }
|
if (timestamp == 0 || (TextSecurePreferences.getLocalNumber(this).equals(recipient.getAddress().serialize())) ) { return; }
|
||||||
updateForNewMessageStatusIfNeeded(newMessageStatus, timestamp);
|
updateForNewMessageStatusIfNeeded(newMessageStatus, timestamp);
|
||||||
if (newMessageStatus.equals("messageFailed") || newMessageStatus.equals("messageSent")) {
|
if (newMessageStatus.equals("messageFailed") || newMessageStatus.equals("messageSent")) {
|
||||||
new Handler().postDelayed(() -> clearMessageStatusIfNeeded(timestamp), 1000);
|
new Handler().postDelayed(() -> clearMessageStatusIfNeeded(timestamp), 1000);
|
||||||
|
@ -49,11 +49,11 @@ public class PushDatabase extends Database {
|
|||||||
values.put(TYPE, envelope.getType());
|
values.put(TYPE, envelope.getType());
|
||||||
values.put(SOURCE, envelope.getSource());
|
values.put(SOURCE, envelope.getSource());
|
||||||
values.put(DEVICE_ID, envelope.getSourceDevice());
|
values.put(DEVICE_ID, envelope.getSourceDevice());
|
||||||
values.put(LEGACY_MSG, envelope.hasLegacyMessage() ? Base64.encodeBytes(envelope.getLegacyMessage()) : "");
|
values.put(LEGACY_MSG, "");
|
||||||
values.put(CONTENT, envelope.hasContent() ? Base64.encodeBytes(envelope.getContent()) : "");
|
values.put(CONTENT, envelope.hasContent() ? Base64.encodeBytes(envelope.getContent()) : "");
|
||||||
values.put(TIMESTAMP, envelope.getTimestamp());
|
values.put(TIMESTAMP, envelope.getTimestamp());
|
||||||
values.put(SERVER_TIMESTAMP, envelope.getServerTimestamp());
|
values.put(SERVER_TIMESTAMP, envelope.getServerTimestamp());
|
||||||
values.put(SERVER_GUID, envelope.getUuid());
|
values.put(SERVER_GUID, "");
|
||||||
|
|
||||||
return databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, values);
|
return databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, values);
|
||||||
}
|
}
|
||||||
@ -68,17 +68,14 @@ public class PushDatabase extends Database {
|
|||||||
null, null, null);
|
null, null, null);
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToNext()) {
|
if (cursor != null && cursor.moveToNext()) {
|
||||||
String legacyMessage = cursor.getString(cursor.getColumnIndexOrThrow(LEGACY_MSG));
|
|
||||||
String content = cursor.getString(cursor.getColumnIndexOrThrow(CONTENT));
|
String content = cursor.getString(cursor.getColumnIndexOrThrow(CONTENT));
|
||||||
|
|
||||||
return new SignalServiceEnvelope(cursor.getInt(cursor.getColumnIndexOrThrow(TYPE)),
|
return new SignalServiceEnvelope(cursor.getInt(cursor.getColumnIndexOrThrow(TYPE)),
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(SOURCE)),
|
cursor.getString(cursor.getColumnIndexOrThrow(SOURCE)),
|
||||||
cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE_ID)),
|
cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE_ID)),
|
||||||
cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP)),
|
cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP)),
|
||||||
Util.isEmpty(legacyMessage) ? null : Base64.decode(legacyMessage),
|
|
||||||
Util.isEmpty(content) ? null : Base64.decode(content),
|
Util.isEmpty(content) ? null : Base64.decode(content),
|
||||||
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_TIMESTAMP)),
|
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_TIMESTAMP)));
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID)));
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
@ -114,7 +111,7 @@ public class PushDatabase extends Database {
|
|||||||
new String[] {String.valueOf(envelope.getType()),
|
new String[] {String.valueOf(envelope.getType()),
|
||||||
envelope.getSource(),
|
envelope.getSource(),
|
||||||
String.valueOf(envelope.getSourceDevice()),
|
String.valueOf(envelope.getSourceDevice()),
|
||||||
envelope.hasLegacyMessage() ? Base64.encodeBytes(envelope.getLegacyMessage()) : "",
|
"",
|
||||||
envelope.hasContent() ? Base64.encodeBytes(envelope.getContent()) : "",
|
envelope.hasContent() ? Base64.encodeBytes(envelope.getContent()) : "",
|
||||||
String.valueOf(envelope.getTimestamp())},
|
String.valueOf(envelope.getTimestamp())},
|
||||||
null, null, null);
|
null, null, null);
|
||||||
@ -144,16 +141,13 @@ public class PushDatabase extends Database {
|
|||||||
int type = cursor.getInt(cursor.getColumnIndexOrThrow(TYPE));
|
int type = cursor.getInt(cursor.getColumnIndexOrThrow(TYPE));
|
||||||
String source = cursor.getString(cursor.getColumnIndexOrThrow(SOURCE));
|
String source = cursor.getString(cursor.getColumnIndexOrThrow(SOURCE));
|
||||||
int deviceId = cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE_ID));
|
int deviceId = cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE_ID));
|
||||||
String legacyMessage = cursor.getString(cursor.getColumnIndexOrThrow(LEGACY_MSG));
|
|
||||||
String content = cursor.getString(cursor.getColumnIndexOrThrow(CONTENT));
|
String content = cursor.getString(cursor.getColumnIndexOrThrow(CONTENT));
|
||||||
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP));
|
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP));
|
||||||
long serverTimestamp = cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_TIMESTAMP));
|
long serverTimestamp = cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_TIMESTAMP));
|
||||||
String serverGuid = cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID));
|
|
||||||
|
|
||||||
return new SignalServiceEnvelope(type, source, deviceId, timestamp,
|
return new SignalServiceEnvelope(type, source, deviceId, timestamp,
|
||||||
legacyMessage != null ? Base64.decode(legacyMessage) : null,
|
|
||||||
content != null ? Base64.decode(content) : null,
|
content != null ? Base64.decode(content) : null,
|
||||||
serverTimestamp, serverGuid);
|
serverTimestamp);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (oldVersion < lokiV21) {
|
if (oldVersion < lokiV21) {
|
||||||
deleteJobRecords(db, "ClosedGroupUpdateMessageSendJob");
|
deleteJobRecords(db,
|
||||||
|
"ClosedGroupUpdateMessageSendJob",
|
||||||
|
"NullMessageSendJob");
|
||||||
}
|
}
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
|
@ -32,7 +32,6 @@ import org.thoughtcrime.securesms.jobs.TypingSendJob;
|
|||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl;
|
import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation;
|
|
||||||
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
|
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
|
||||||
import org.thoughtcrime.securesms.push.MessageSenderEventListener;
|
import org.thoughtcrime.securesms.push.MessageSenderEventListener;
|
||||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||||
@ -88,20 +87,15 @@ public class SignalCommunicationModule {
|
|||||||
@Provides
|
@Provides
|
||||||
public synchronized SignalServiceMessageSender provideSignalMessageSender() {
|
public synchronized SignalServiceMessageSender provideSignalMessageSender() {
|
||||||
if (this.messageSender == null) {
|
if (this.messageSender == null) {
|
||||||
this.messageSender = new SignalServiceMessageSender(networkAccess.getConfiguration(context),
|
this.messageSender = new SignalServiceMessageSender(new DynamicCredentialsProvider(context),
|
||||||
new DynamicCredentialsProvider(context),
|
|
||||||
new SignalProtocolStoreImpl(context),
|
new SignalProtocolStoreImpl(context),
|
||||||
BuildConfig.USER_AGENT,
|
|
||||||
Optional.fromNullable(IncomingMessageObserver.getPipe()),
|
Optional.fromNullable(IncomingMessageObserver.getPipe()),
|
||||||
Optional.fromNullable(IncomingMessageObserver.getUnidentifiedPipe()),
|
Optional.fromNullable(IncomingMessageObserver.getUnidentifiedPipe()),
|
||||||
Optional.of(new MessageSenderEventListener(context)),
|
|
||||||
TextSecurePreferences.getLocalNumber(context),
|
TextSecurePreferences.getLocalNumber(context),
|
||||||
DatabaseFactory.getLokiAPIDatabase(context),
|
DatabaseFactory.getLokiAPIDatabase(context),
|
||||||
DatabaseFactory.getLokiThreadDatabase(context),
|
DatabaseFactory.getLokiThreadDatabase(context),
|
||||||
DatabaseFactory.getLokiMessageDatabase(context),
|
DatabaseFactory.getLokiMessageDatabase(context),
|
||||||
null, // DatabaseFactory.getLokiPreKeyBundleDatabase(context)
|
|
||||||
new SessionProtocolImpl(context),
|
new SessionProtocolImpl(context),
|
||||||
new SessionResetImplementation(context),
|
|
||||||
DatabaseFactory.getLokiUserDatabase(context),
|
DatabaseFactory.getLokiUserDatabase(context),
|
||||||
DatabaseFactory.getGroupDatabase(context),
|
DatabaseFactory.getGroupDatabase(context),
|
||||||
((ApplicationContext)context.getApplicationContext()).broadcaster);
|
((ApplicationContext)context.getApplicationContext()).broadcaster);
|
||||||
|
@ -17,7 +17,6 @@ import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintOb
|
|||||||
import org.thoughtcrime.securesms.loki.api.PrepareAttachmentAudioExtrasJob;
|
import org.thoughtcrime.securesms.loki.api.PrepareAttachmentAudioExtrasJob;
|
||||||
import org.thoughtcrime.securesms.loki.api.ResetThreadSessionJob;
|
import org.thoughtcrime.securesms.loki.api.ResetThreadSessionJob;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupUpdateMessageSendJobV2;
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupUpdateMessageSendJobV2;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.NullMessageSendJob;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -41,7 +40,6 @@ public final class JobManagerFactories {
|
|||||||
put(MmsDownloadJob.KEY, new MmsDownloadJob.Factory());
|
put(MmsDownloadJob.KEY, new MmsDownloadJob.Factory());
|
||||||
put(MmsReceiveJob.KEY, new MmsReceiveJob.Factory());
|
put(MmsReceiveJob.KEY, new MmsReceiveJob.Factory());
|
||||||
put(MmsSendJob.KEY, new MmsSendJob.Factory());
|
put(MmsSendJob.KEY, new MmsSendJob.Factory());
|
||||||
put(NullMessageSendJob.KEY, new NullMessageSendJob.Factory());
|
|
||||||
put(PushContentReceiveJob.KEY, new PushContentReceiveJob.Factory());
|
put(PushContentReceiveJob.KEY, new PushContentReceiveJob.Factory());
|
||||||
put(PushDecryptJob.KEY, new PushDecryptJob.Factory());
|
put(PushDecryptJob.KEY, new PushDecryptJob.Factory());
|
||||||
put(PushGroupSendJob.KEY, new PushGroupSendJob.Factory());
|
put(PushGroupSendJob.KEY, new PushGroupSendJob.Factory());
|
||||||
|
@ -17,19 +17,8 @@ import com.annimon.stream.Stream;
|
|||||||
import org.session.libsession.messaging.jobs.Data;
|
import org.session.libsession.messaging.jobs.Data;
|
||||||
import org.session.libsession.utilities.MediaTypes;
|
import org.session.libsession.utilities.MediaTypes;
|
||||||
import org.session.libsignal.metadata.InvalidMetadataMessageException;
|
import org.session.libsignal.metadata.InvalidMetadataMessageException;
|
||||||
import org.session.libsignal.metadata.InvalidMetadataVersionException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolDuplicateMessageException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolInvalidKeyException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolInvalidKeyIdException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolInvalidMessageException;
|
import org.session.libsignal.metadata.ProtocolInvalidMessageException;
|
||||||
import org.session.libsignal.metadata.ProtocolInvalidVersionException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolLegacyMessageException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolNoSessionException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolUntrustedIdentityException;
|
|
||||||
import org.session.libsignal.metadata.SelfSendException;
|
|
||||||
import org.session.libsignal.service.api.crypto.SignalServiceCipher;
|
import org.session.libsignal.service.api.crypto.SignalServiceCipher;
|
||||||
import org.session.libsignal.service.loki.api.crypto.SessionProtocol;
|
|
||||||
import org.session.libsignal.utilities.PromiseUtilities;
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
|
|
||||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||||
@ -48,13 +37,10 @@ import org.session.libsession.utilities.TextSecurePreferences;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.contactshare.ContactModelMapper;
|
import org.thoughtcrime.securesms.contactshare.ContactModelMapper;
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
|
||||||
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
|
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||||
import org.thoughtcrime.securesms.database.GroupReceiptDatabase;
|
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase;
|
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
@ -79,26 +65,19 @@ import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
|||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2;
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
|
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation;
|
|
||||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
||||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.MmsException;
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage;
|
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
|
||||||
import org.thoughtcrime.securesms.mms.StickerSlide;
|
import org.thoughtcrime.securesms.mms.StickerSlide;
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
|
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
|
||||||
import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage;
|
import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage;
|
||||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage;
|
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||||
import org.session.libsignal.utilities.Hex;
|
import org.session.libsignal.utilities.Hex;
|
||||||
import org.session.libsignal.libsignal.InvalidMessageException;
|
import org.session.libsignal.libsignal.InvalidMessageException;
|
||||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol;
|
|
||||||
import org.session.libsignal.libsignal.state.SignalProtocolStore;
|
import org.session.libsignal.libsignal.state.SignalProtocolStore;
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.api.SignalServiceMessageSender;
|
import org.session.libsignal.service.api.SignalServiceMessageSender;
|
||||||
@ -111,16 +90,14 @@ import org.session.libsignal.service.api.messages.SignalServiceReceiptMessage;
|
|||||||
import org.session.libsignal.service.api.messages.SignalServiceTypingMessage;
|
import org.session.libsignal.service.api.messages.SignalServiceTypingMessage;
|
||||||
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
||||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager;
|
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager;
|
||||||
import org.session.libsignal.service.loki.utilities.PublicKeyValidation;
|
import org.session.libsignal.service.loki.utilities.PublicKeyValidation;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@ -242,10 +219,9 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
try {
|
try {
|
||||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||||
SignalProtocolStore axolotlStore = new SignalProtocolStoreImpl(context);
|
SignalProtocolStore axolotlStore = new SignalProtocolStoreImpl(context);
|
||||||
SessionResetProtocol sessionResetProtocol = new SessionResetImplementation(context);
|
|
||||||
SignalServiceAddress localAddress = new SignalServiceAddress(TextSecurePreferences.getLocalNumber(context));
|
SignalServiceAddress localAddress = new SignalServiceAddress(TextSecurePreferences.getLocalNumber(context));
|
||||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(context);
|
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(context);
|
||||||
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, axolotlStore, sessionResetProtocol, new SessionProtocolImpl(context), apiDB);
|
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, axolotlStore, new SessionProtocolImpl(context), apiDB);
|
||||||
|
|
||||||
SignalServiceContent content = cipher.decrypt(envelope);
|
SignalServiceContent content = cipher.decrypt(envelope);
|
||||||
|
|
||||||
@ -254,8 +230,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionManagementProtocol.handlePreKeyBundleMessageIfNeeded(context, content);
|
|
||||||
|
|
||||||
SessionMetaProtocol.handleProfileUpdateIfNeeded(context, content);
|
SessionMetaProtocol.handleProfileUpdateIfNeeded(context, content);
|
||||||
|
|
||||||
if (content.configurationMessageProto.isPresent()) {
|
if (content.configurationMessageProto.isPresent()) {
|
||||||
@ -341,7 +315,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (threadId != null) {
|
if (threadId != null) {
|
||||||
SessionManagementProtocol.handleEndSessionMessageIfNeeded(context, content);
|
|
||||||
messageNotifier.updateNotification(context, threadId);
|
messageNotifier.updateNotification(context, threadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -706,82 +679,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
smsDatabase.markAsDecryptFailed(smsMessageId.get());
|
smsDatabase.markAsDecryptFailed(smsMessageId.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canRecoverAutomatically(e)) {
|
|
||||||
Recipient recipient = Recipient.from(context, Address.fromSerialized(sender), false);
|
|
||||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context);
|
|
||||||
long threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
|
|
||||||
threadDB.addSessionRestoreDevice(threadID, sender);
|
|
||||||
SessionManagementProtocol.startSessionReset(context, sender);
|
|
||||||
} else {
|
|
||||||
SessionManagementProtocol.triggerSessionRestorationUI(context, sender, timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canRecoverAutomatically(Throwable e) {
|
|
||||||
// Corrupt message exception
|
|
||||||
if (e.getCause() != null) {
|
|
||||||
Throwable e2 = e.getCause();
|
|
||||||
if (e2.getCause() != null) {
|
|
||||||
Throwable e3 = e2.getCause();
|
|
||||||
if (e3 instanceof InvalidMessageException) {
|
|
||||||
String message = e3.getMessage();
|
|
||||||
return (message != null && message.startsWith("Bad Mac!"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleNoSessionMessage(@NonNull String sender, int senderDevice, long timestamp,
|
|
||||||
@NonNull Optional<Long> smsMessageId)
|
|
||||||
{
|
|
||||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
|
||||||
if (!SessionMetaProtocol.shouldIgnoreDecryptionException(context, timestamp)) {
|
|
||||||
if (!smsMessageId.isPresent()) {
|
|
||||||
Optional<InsertResult> insertResult = insertPlaceholder(sender, senderDevice, timestamp);
|
|
||||||
|
|
||||||
if (insertResult.isPresent()) {
|
|
||||||
smsDatabase.markAsNoSession(insertResult.get().getMessageId());
|
|
||||||
messageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
smsDatabase.markAsNoSession(smsMessageId.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleLegacyMessage(@NonNull String sender, int senderDevice, long timestamp,
|
|
||||||
@NonNull Optional<Long> smsMessageId)
|
|
||||||
{
|
|
||||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
|
||||||
|
|
||||||
if (!smsMessageId.isPresent()) {
|
|
||||||
Optional<InsertResult> insertResult = insertPlaceholder(sender, senderDevice, timestamp);
|
|
||||||
|
|
||||||
if (insertResult.isPresent()) {
|
|
||||||
smsDatabase.markAsLegacyVersion(insertResult.get().getMessageId());
|
|
||||||
messageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
smsDatabase.markAsLegacyVersion(smsMessageId.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private void handleDuplicateMessage(@NonNull String sender, int senderDeviceId, long timestamp,
|
|
||||||
@NonNull Optional<Long> smsMessageId)
|
|
||||||
{
|
|
||||||
// Let's start ignoring these now
|
|
||||||
// SmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
|
||||||
//
|
|
||||||
// if (smsMessageId <= 0) {
|
|
||||||
// Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
|
||||||
// smsDatabase.markAsDecryptDuplicate(messageAndThreadId.first);
|
|
||||||
// MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
|
||||||
// } else {
|
|
||||||
// smsDatabase.markAsDecryptDuplicate(smsMessageId);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNeedsDeliveryReceipt(@NonNull SignalServiceContent content,
|
private void handleNeedsDeliveryReceipt(@NonNull SignalServiceContent content,
|
||||||
@ -905,42 +802,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
PointerAttachment.forPointersOfDataMessage(quote.get().getAttachments())));
|
PointerAttachment.forPointersOfDataMessage(quote.get().getAttachments())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<Attachment> getStickerAttachment(Optional<SignalServiceDataMessage.Sticker> sticker) {
|
|
||||||
if (!sticker.isPresent()) {
|
|
||||||
return Optional.absent();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sticker.get().getPackId() == null || sticker.get().getPackKey() == null || sticker.get().getAttachment() == null) {
|
|
||||||
Log.w(TAG, "Malformed sticker!");
|
|
||||||
return Optional.absent();
|
|
||||||
}
|
|
||||||
|
|
||||||
String packId = Hex.toStringCondensed(sticker.get().getPackId());
|
|
||||||
String packKey = Hex.toStringCondensed(sticker.get().getPackKey());
|
|
||||||
int stickerId = sticker.get().getStickerId();
|
|
||||||
StickerLocator stickerLocator = new StickerLocator(packId, packKey, stickerId);
|
|
||||||
StickerDatabase stickerDatabase = DatabaseFactory.getStickerDatabase(context);
|
|
||||||
StickerRecord stickerRecord = stickerDatabase.getSticker(stickerLocator.getPackId(), stickerLocator.getStickerId(), false);
|
|
||||||
|
|
||||||
if (stickerRecord != null) {
|
|
||||||
return Optional.of(new UriAttachment(stickerRecord.getUri(),
|
|
||||||
stickerRecord.getUri(),
|
|
||||||
MediaTypes.IMAGE_WEBP,
|
|
||||||
AttachmentDatabase.TRANSFER_PROGRESS_DONE,
|
|
||||||
stickerRecord.getSize(),
|
|
||||||
StickerSlide.WIDTH,
|
|
||||||
StickerSlide.HEIGHT,
|
|
||||||
null,
|
|
||||||
String.valueOf(new SecureRandom().nextLong()),
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
stickerLocator));
|
|
||||||
} else {
|
|
||||||
return Optional.of(PointerAttachment.forPointer(Optional.of(sticker.get().getAttachment()), stickerLocator).get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<List<Contact>> getContacts(Optional<List<SharedContact>> sharedContacts) {
|
private Optional<List<Contact>> getContacts(Optional<List<SharedContact>> sharedContacts) {
|
||||||
if (!sharedContacts.isPresent()) return Optional.absent();
|
if (!sharedContacts.isPresent()) return Optional.absent();
|
||||||
|
|
||||||
@ -1069,10 +930,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isGroupChatMessage(SignalServiceContent content) {
|
|
||||||
return content.getDataMessage().isPresent() && content.getDataMessage().get().isGroupMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resetRecipientToPush(@NonNull Recipient recipient) {
|
private void resetRecipientToPush(@NonNull Recipient recipient) {
|
||||||
if (recipient.isForceSmsSelection()) {
|
if (recipient.isForceSmsSelection()) {
|
||||||
DatabaseFactory.getRecipientDatabase(context).setForceSmsSelection(recipient, false);
|
DatabaseFactory.getRecipientDatabase(context).setForceSmsSelection(recipient, false);
|
||||||
|
@ -39,12 +39,10 @@ import org.session.libsignal.service.api.messages.SendMessageResult;
|
|||||||
import org.session.libsignal.service.api.messages.SignalServiceAttachment;
|
import org.session.libsignal.service.api.messages.SignalServiceAttachment;
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
|
import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage.Preview;
|
import org.session.libsignal.service.api.messages.SignalServiceDataMessage.Preview;
|
||||||
import org.session.libsignal.service.api.messages.multidevice.SignalServiceSyncMessage;
|
|
||||||
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
||||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||||
import org.session.libsignal.service.api.push.exceptions.UnregisteredUserException;
|
import org.session.libsignal.service.api.push.exceptions.UnregisteredUserException;
|
||||||
import org.session.libsignal.service.loki.api.SnodeAPI;
|
import org.session.libsignal.service.loki.api.SnodeAPI;
|
||||||
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol;
|
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -285,7 +283,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
|||||||
.asExpirationUpdate(message.isExpirationUpdate())
|
.asExpirationUpdate(message.isExpirationUpdate())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (SessionMetaProtocol.shared.isNoteToSelf(address.getNumber())) {
|
if (userPublicKey == address.getNumber()) {
|
||||||
// Loki - Device link messages don't go through here
|
// Loki - Device link messages don't go through here
|
||||||
SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccessPair, mediaMessage);
|
SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccessPair, mediaMessage);
|
||||||
if (result.getLokiAPIError() != null) {
|
if (result.getLokiAPIError() != null) {
|
||||||
|
@ -33,10 +33,7 @@ public abstract class PushReceivedJob extends BaseJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (envelope.isReceipt()) {
|
if (envelope.isUnidentifiedSender() || envelope.isClosedGroupCiphertext()) {
|
||||||
handleReceipt(envelope);
|
|
||||||
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage()
|
|
||||||
|| envelope.isUnidentifiedSender() || envelope.isFallbackMessage() || envelope.isClosedGroupCiphertext()) {
|
|
||||||
handleMessage(envelope, isPushNotification);
|
handleMessage(envelope, isPushNotification);
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Received envelope of unknown type: " + envelope.getType());
|
Log.w(TAG, "Received envelope of unknown type: " + envelope.getType());
|
||||||
@ -51,13 +48,6 @@ public abstract class PushReceivedJob extends BaseJob {
|
|||||||
new PushDecryptJob(context).processMessage(envelope, isPushNotification);
|
new PushDecryptJob(context).processMessage(envelope, isPushNotification);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
|
||||||
private void handleReceipt(SignalServiceEnvelope envelope) {
|
|
||||||
Log.i(TAG, String.format("Received receipt: (XXXXX, %d)", envelope.getTimestamp()));
|
|
||||||
DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()),
|
|
||||||
envelope.getTimestamp()), System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isActiveNumber(@NonNull Recipient recipient) {
|
private boolean isActiveNumber(@NonNull Recipient recipient) {
|
||||||
return recipient.resolve().getRegistered() == Recipient.RegisteredState.REGISTERED;
|
return recipient.resolve().getRegistered() == Recipient.RegisteredState.REGISTERED;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
|||||||
import org.session.libsession.messaging.sending_receiving.sharecontacts.Contact;
|
import org.session.libsession.messaging.sending_receiving.sharecontacts.Contact;
|
||||||
import org.session.libsession.utilities.MediaTypes;
|
import org.session.libsession.utilities.MediaTypes;
|
||||||
import org.session.libsignal.utilities.Base64;
|
import org.session.libsignal.utilities.Base64;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
@ -34,13 +33,10 @@ import org.thoughtcrime.securesms.util.BitmapUtil;
|
|||||||
import org.session.libsignal.utilities.Hex;
|
import org.session.libsignal.utilities.Hex;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair;
|
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceAttachment;
|
import org.session.libsignal.service.api.messages.SignalServiceAttachment;
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceAttachmentPointer;
|
import org.session.libsignal.service.api.messages.SignalServiceAttachmentPointer;
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
|
import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage.Preview;
|
import org.session.libsignal.service.api.messages.SignalServiceDataMessage.Preview;
|
||||||
import org.session.libsignal.service.api.messages.multidevice.SentTranscriptMessage;
|
|
||||||
import org.session.libsignal.service.api.messages.multidevice.SignalServiceSyncMessage;
|
|
||||||
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
||||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
@ -55,7 +51,6 @@ import java.util.concurrent.TimeUnit;
|
|||||||
public abstract class PushSendJob extends SendJob {
|
public abstract class PushSendJob extends SendJob {
|
||||||
|
|
||||||
private static final String TAG = PushSendJob.class.getSimpleName();
|
private static final String TAG = PushSendJob.class.getSimpleName();
|
||||||
private static final long CERTIFICATE_EXPIRATION_BUFFER = TimeUnit.DAYS.toMillis(1);
|
|
||||||
|
|
||||||
protected PushSendJob(Job.Parameters parameters) {
|
protected PushSendJob(Job.Parameters parameters) {
|
||||||
super(parameters);
|
super(parameters);
|
||||||
@ -72,14 +67,6 @@ public abstract class PushSendJob extends SendJob {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final void onSend() throws Exception {
|
protected final void onSend() throws Exception {
|
||||||
// if (TextSecurePreferences.getSignedPreKeyFailureCount(context) > 5) {
|
|
||||||
// ApplicationContext.getInstance(context)
|
|
||||||
// .getJobManager()
|
|
||||||
// .add(new RotateSignedPreKeyJob());
|
|
||||||
//
|
|
||||||
// throw new TextSecureExpiredException("Too many signed prekey rotation failures");
|
|
||||||
// }
|
|
||||||
|
|
||||||
onPushSend();
|
onPushSend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,11 +30,9 @@ import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair;
|
|||||||
import org.session.libsignal.service.api.crypto.UntrustedIdentityException;
|
import org.session.libsignal.service.api.crypto.UntrustedIdentityException;
|
||||||
import org.session.libsignal.service.api.messages.SendMessageResult;
|
import org.session.libsignal.service.api.messages.SendMessageResult;
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
|
import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
|
||||||
import org.session.libsignal.service.api.messages.multidevice.SignalServiceSyncMessage;
|
|
||||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||||
import org.session.libsignal.service.api.push.exceptions.UnregisteredUserException;
|
import org.session.libsignal.service.api.push.exceptions.UnregisteredUserException;
|
||||||
import org.session.libsignal.service.loki.api.SnodeAPI;
|
import org.session.libsignal.service.loki.api.SnodeAPI;
|
||||||
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -224,7 +222,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
|||||||
.asEndSessionMessage(message.isEndSession())
|
.asEndSessionMessage(message.isEndSession())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (SessionMetaProtocol.shared.isNoteToSelf(address.getNumber())) {
|
if (userPublicKey.equals(address.getNumber())) {
|
||||||
// Loki - Device link messages don't go through here
|
// Loki - Device link messages don't go through here
|
||||||
SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage);
|
SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage);
|
||||||
if (result.getLokiAPIError() != null) {
|
if (result.getLokiAPIError() != null) {
|
||||||
|
@ -87,16 +87,14 @@ public class TypingSendJob extends BaseJob implements InjectableType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Recipient> recipients = Collections.singletonList(recipient);
|
List<Recipient> recipients = Collections.singletonList(recipient);
|
||||||
Optional<byte[]> groupId = Optional.absent();
|
|
||||||
|
|
||||||
if (recipient.isGroupRecipient()) {
|
if (recipient.isGroupRecipient()) {
|
||||||
recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.getAddress().toGroupString(), false);
|
recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.getAddress().toGroupString(), false);
|
||||||
groupId = Optional.of(GroupUtil.getDecodedGroupIDAsData(recipient.getAddress().toGroupString()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<SignalServiceAddress> addresses = Stream.of(recipients).map(r -> new SignalServiceAddress(r.getAddress().serialize())).toList();
|
List<SignalServiceAddress> addresses = Stream.of(recipients).map(r -> new SignalServiceAddress(r.getAddress().serialize())).toList();
|
||||||
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(recipients).map(r -> UnidentifiedAccessUtil.getAccessFor(context, r)).toList();
|
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(recipients).map(r -> UnidentifiedAccessUtil.getAccessFor(context, r)).toList();
|
||||||
SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis(), groupId);
|
SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis());
|
||||||
|
|
||||||
messageSender.sendTyping(addresses, unidentifiedAccess, typingMessage);
|
messageSender.sendTyping(addresses, unidentifiedAccess, typingMessage);
|
||||||
}
|
}
|
||||||
|
@ -193,8 +193,6 @@ class BackupRestoreViewModel(application: Application): AndroidViewModel(applica
|
|||||||
application.setUpStorageAPIIfNeeded()
|
application.setUpStorageAPIIfNeeded()
|
||||||
application.setUpP2PAPIIfNeeded()
|
application.setUpP2PAPIIfNeeded()
|
||||||
|
|
||||||
HomeActivity.requestResetAllSessionsOnStartup(context)
|
|
||||||
|
|
||||||
BackupRestoreResult.SUCCESS
|
BackupRestoreResult.SUCCESS
|
||||||
} catch (e: DatabaseDowngradeException) {
|
} catch (e: DatabaseDowngradeException) {
|
||||||
Log.w(TAG, "Failed due to the backup being from a newer version of Signal.", e)
|
Log.w(TAG, "Failed due to the backup being from a newer version of Signal.", e)
|
||||||
|
@ -33,7 +33,6 @@ import org.session.libsession.utilities.GroupUtil
|
|||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
import org.thoughtcrime.securesms.loki.api.ResetThreadSessionJob
|
import org.thoughtcrime.securesms.loki.api.ResetThreadSessionJob
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
|
|
||||||
import org.thoughtcrime.securesms.loki.utilities.*
|
import org.thoughtcrime.securesms.loki.utilities.*
|
||||||
import org.thoughtcrime.securesms.loki.views.ConversationView
|
import org.thoughtcrime.securesms.loki.views.ConversationView
|
||||||
import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetViewDelegate
|
import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetViewDelegate
|
||||||
@ -44,8 +43,7 @@ import org.session.libsession.utilities.TextSecurePreferences
|
|||||||
import org.session.libsession.utilities.TextSecurePreferences.getBooleanPreference
|
import org.session.libsession.utilities.TextSecurePreferences.getBooleanPreference
|
||||||
import org.session.libsession.utilities.TextSecurePreferences.setBooleanPreference
|
import org.session.libsession.utilities.TextSecurePreferences.setBooleanPreference
|
||||||
import org.session.libsession.utilities.Util
|
import org.session.libsession.utilities.Util
|
||||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager
|
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager
|
||||||
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol
|
|
||||||
import org.session.libsignal.utilities.ThreadUtils
|
import org.session.libsignal.utilities.ThreadUtils
|
||||||
import org.session.libsignal.service.loki.utilities.toHexString
|
import org.session.libsignal.service.loki.utilities.toHexString
|
||||||
import org.thoughtcrime.securesms.loki.dialogs.*
|
import org.thoughtcrime.securesms.loki.dialogs.*
|
||||||
@ -54,31 +52,6 @@ import java.io.IOException
|
|||||||
|
|
||||||
class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListener, SeedReminderViewDelegate, NewConversationButtonSetViewDelegate {
|
class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListener, SeedReminderViewDelegate, NewConversationButtonSetViewDelegate {
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val PREF_RESET_ALL_SESSIONS_ON_START_UP = "pref_reset_all_sessions_on_start_up"
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun requestResetAllSessionsOnStartup(context: Context) {
|
|
||||||
setBooleanPreference(context, PREF_RESET_ALL_SESSIONS_ON_START_UP, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun scheduleResetAllSessionsIfRequested(context: Context) {
|
|
||||||
if (!getBooleanPreference(context, PREF_RESET_ALL_SESSIONS_ON_START_UP, false)) return
|
|
||||||
setBooleanPreference(context, PREF_RESET_ALL_SESSIONS_ON_START_UP, false)
|
|
||||||
|
|
||||||
val jobManager = ApplicationContext.getInstance(context).jobManager
|
|
||||||
|
|
||||||
DatabaseFactory.getThreadDatabase(context).conversationListQuick.forEach { tuple ->
|
|
||||||
val threadId: Long = tuple.first
|
|
||||||
val recipientAddress: String = tuple.second
|
|
||||||
jobManager.add(ResetThreadSessionJob(
|
|
||||||
Address.fromSerialized(recipientAddress),
|
|
||||||
threadId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var glide: GlideRequests
|
private lateinit var glide: GlideRequests
|
||||||
private var broadcastReceiver: BroadcastReceiver? = null
|
private var broadcastReceiver: BroadcastReceiver? = null
|
||||||
|
|
||||||
@ -165,10 +138,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
|||||||
val threadDB = DatabaseFactory.getLokiThreadDatabase(this)
|
val threadDB = DatabaseFactory.getLokiThreadDatabase(this)
|
||||||
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||||
val sessionResetImpl = SessionResetImplementation(this)
|
|
||||||
if (userPublicKey != null) {
|
if (userPublicKey != null) {
|
||||||
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
||||||
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
|
||||||
application.publicChatManager.startPollersIfNeeded()
|
application.publicChatManager.startPollersIfNeeded()
|
||||||
}
|
}
|
||||||
IP2Country.configureIfNeeded(this)
|
IP2Country.configureIfNeeded(this)
|
||||||
|
@ -153,11 +153,23 @@ class PublicChatPoller(private val context: Context, private val group: PublicCh
|
|||||||
signalLinkPreviews.add(SignalServiceDataMessage.Preview(linkPreview.linkPreviewURL!!, linkPreview.linkPreviewTitle!!, Optional.of(attachment)))
|
signalLinkPreviews.add(SignalServiceDataMessage.Preview(linkPreview.linkPreviewURL!!, linkPreview.linkPreviewTitle!!, Optional.of(attachment)))
|
||||||
}
|
}
|
||||||
val body = if (message.body == message.timestamp.toString()) "" else message.body // Workaround for the fact that the back-end doesn't accept messages without a body
|
val body = if (message.body == message.timestamp.toString()) "" else message.body // Workaround for the fact that the back-end doesn't accept messages without a body
|
||||||
return SignalServiceDataMessage(message.timestamp, serviceGroup, attachments, body, 0, false, null, quote, null, signalLinkPreviews)
|
val syncTarget = if (message.senderPublicKey == userHexEncodedPublicKey) group.id else null
|
||||||
|
return SignalServiceDataMessage(message.timestamp, serviceGroup, attachments, body, 0, false, null, quote, null, signalLinkPreviews, null, syncTarget)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun pollForNewMessages(): Promise<Unit, Exception> {
|
fun pollForNewMessages(): Promise<Unit, Exception> {
|
||||||
fun processIncomingMessage(message: PublicChatMessage) {
|
if (isPollOngoing) { return Promise.of(Unit) }
|
||||||
|
isPollOngoing = true
|
||||||
|
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
||||||
|
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
|
||||||
|
FileServerAPI.configure(userHexEncodedPublicKey, userPrivateKey, apiDB)
|
||||||
|
// Kovenant propagates a context to chained promises, so LokiPublicChatAPI.sharedContext should be used for all of the below
|
||||||
|
val promise = api.getMessages(group.channel, group.server).bind(PublicChatAPI.sharedContext) { messages ->
|
||||||
|
Promise.of(messages)
|
||||||
|
}
|
||||||
|
promise.successBackground { messages ->
|
||||||
|
// Process messages in the background
|
||||||
|
messages.forEach { message ->
|
||||||
// If the sender of the current message is not a slave device, set the display name in the database
|
// If the sender of the current message is not a slave device, set the display name in the database
|
||||||
val senderDisplayName = "${message.displayName} (...${message.senderPublicKey.takeLast(8)})"
|
val senderDisplayName = "${message.displayName} (...${message.senderPublicKey.takeLast(8)})"
|
||||||
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.senderPublicKey, senderDisplayName)
|
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.senderPublicKey, senderDisplayName)
|
||||||
@ -181,57 +193,6 @@ class PublicChatPoller(private val context: Context, private val group: PublicCh
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun processOutgoingMessage(message: PublicChatMessage) {
|
|
||||||
val messageServerID = message.serverID ?: return
|
|
||||||
val messageID = DatabaseFactory.getLokiMessageDatabase(context).getMessageID(messageServerID)
|
|
||||||
var isDuplicate = false
|
|
||||||
if (messageID != null) {
|
|
||||||
isDuplicate = DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageID) >= 0
|
|
||||||
|| DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageID) >= 0
|
|
||||||
}
|
|
||||||
if (isDuplicate) { return }
|
|
||||||
if (message.body.isEmpty() && message.attachments.isEmpty() && message.quote == null) { return }
|
|
||||||
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
|
||||||
val dataMessage = getDataMessage(message)
|
|
||||||
SessionMetaProtocol.dropFromTimestampCacheIfNeeded(message.serverTimestamp)
|
|
||||||
val transcript = SentTranscriptMessage(userHexEncodedPublicKey, message.serverTimestamp, dataMessage, dataMessage.expiresInSeconds.toLong(), Collections.singletonMap(userHexEncodedPublicKey, false))
|
|
||||||
transcript.messageServerID = messageServerID
|
|
||||||
if (dataMessage.quote.isPresent || (dataMessage.attachments.isPresent && dataMessage.attachments.get().size > 0) || dataMessage.previews.isPresent) {
|
|
||||||
PushDecryptJob(context).handleSynchronizeSentMediaMessage(transcript)
|
|
||||||
} else {
|
|
||||||
PushDecryptJob(context).handleSynchronizeSentTextMessage(transcript)
|
|
||||||
}
|
|
||||||
// If we got a message from our master device then make sure our mapping stays in sync
|
|
||||||
val recipient = Recipient.from(context, Address.fromSerialized(message.senderPublicKey), false)
|
|
||||||
if (message.profilePicture != null) {
|
|
||||||
val profileKey = message.profilePicture!!.profileKey
|
|
||||||
val url = message.profilePicture!!.url
|
|
||||||
if (recipient.profileKey == null || !MessageDigest.isEqual(recipient.profileKey, profileKey)) {
|
|
||||||
val database = DatabaseFactory.getRecipientDatabase(context)
|
|
||||||
database.setProfileKey(recipient, profileKey)
|
|
||||||
database.setProfileAvatar(recipient, url)
|
|
||||||
ApplicationContext.getInstance(context).updateOpenGroupProfilePicturesIfNeeded()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isPollOngoing) { return Promise.of(Unit) }
|
|
||||||
isPollOngoing = true
|
|
||||||
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
|
||||||
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
|
|
||||||
FileServerAPI.configure(userHexEncodedPublicKey, userPrivateKey, apiDB)
|
|
||||||
// Kovenant propagates a context to chained promises, so LokiPublicChatAPI.sharedContext should be used for all of the below
|
|
||||||
val promise = api.getMessages(group.channel, group.server).bind(PublicChatAPI.sharedContext) { messages ->
|
|
||||||
Promise.of(messages)
|
|
||||||
}
|
|
||||||
promise.successBackground { messages ->
|
|
||||||
// Process messages in the background
|
|
||||||
messages.forEach { message ->
|
|
||||||
if (message.senderPublicKey == userHexEncodedPublicKey) {
|
|
||||||
processOutgoingMessage(message)
|
|
||||||
} else {
|
|
||||||
processIncomingMessage(message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
isCaughtUp = true
|
isCaughtUp = true
|
||||||
isPollOngoing = false
|
isPollOngoing = false
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ import org.session.libsession.messaging.threads.recipients.Recipient
|
|||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat
|
import org.session.libsignal.service.loki.api.opengroups.PublicChat
|
||||||
|
|
||||||
import org.session.libsignal.libsignal.loki.SessionResetStatus
|
|
||||||
import org.session.libsignal.utilities.JsonUtil
|
import org.session.libsignal.utilities.JsonUtil
|
||||||
import org.session.libsignal.service.loki.database.LokiThreadDatabaseProtocol
|
import org.session.libsignal.service.loki.database.LokiThreadDatabaseProtocol
|
||||||
import org.session.libsignal.service.loki.utilities.PublicKeyValidation
|
import org.session.libsignal.service.loki.utilities.PublicKeyValidation
|
||||||
@ -39,34 +38,6 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
|||||||
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getThreadID(messageID: Long): Long {
|
|
||||||
return DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSessionResetStatus(hexEncodedPublicKey: String): SessionResetStatus {
|
|
||||||
val threadID = getThreadID(hexEncodedPublicKey)
|
|
||||||
val database = databaseHelper.readableDatabase
|
|
||||||
val result = database.get(sessionResetTable, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
|
|
||||||
cursor.getInt(sessionResetStatus)
|
|
||||||
}
|
|
||||||
return if (result != null) {
|
|
||||||
SessionResetStatus.values().first { it.rawValue == result }
|
|
||||||
} else {
|
|
||||||
SessionResetStatus.NONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setSessionResetStatus(hexEncodedPublicKey: String, sessionResetStatus: SessionResetStatus) {
|
|
||||||
val threadID = getThreadID(hexEncodedPublicKey)
|
|
||||||
val database = databaseHelper.writableDatabase
|
|
||||||
val contentValues = ContentValues(2)
|
|
||||||
contentValues.put(Companion.threadID, threadID)
|
|
||||||
contentValues.put(Companion.sessionResetStatus, sessionResetStatus.rawValue)
|
|
||||||
database.insertOrUpdate(sessionResetTable, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
|
||||||
notifyConversationListListeners()
|
|
||||||
notifyConversationListeners(threadID)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAllPublicChats(): Map<Long, PublicChat> {
|
fun getAllPublicChats(): Map<Long, PublicChat> {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
|
@ -13,7 +13,7 @@ import org.session.libsignal.libsignal.util.guava.Optional
|
|||||||
import org.session.libsignal.service.api.push.SignalServiceAddress
|
import org.session.libsignal.service.api.push.SignalServiceAddress
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage
|
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage
|
||||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities
|
import org.session.libsignal.service.loki.utilities.TTLUtilities
|
||||||
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
||||||
import org.session.libsignal.service.loki.utilities.toHexString
|
import org.session.libsignal.service.loki.utilities.toHexString
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
@ -25,7 +25,6 @@ import org.session.libsignal.utilities.logging.Log
|
|||||||
import org.thoughtcrime.securesms.loki.utilities.recipient
|
import org.thoughtcrime.securesms.loki.utilities.recipient
|
||||||
import org.session.libsignal.utilities.Hex
|
import org.session.libsignal.utilities.Hex
|
||||||
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class ClosedGroupUpdateMessageSendJobV2 private constructor(parameters: Parameters, private val destination: String, private val kind: Kind, private val sentTime: Long) : BaseJob(parameters) {
|
class ClosedGroupUpdateMessageSendJobV2 private constructor(parameters: Parameters, private val destination: String, private val kind: Kind, private val sentTime: Long) : BaseJob(parameters) {
|
||||||
|
@ -8,6 +8,7 @@ import org.session.libsession.utilities.TextSecurePreferences
|
|||||||
import org.session.libsignal.libsignal.util.guava.Optional
|
import org.session.libsignal.libsignal.util.guava.Optional
|
||||||
import org.session.libsignal.service.api.push.SignalServiceAddress
|
import org.session.libsignal.service.api.push.SignalServiceAddress
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||||
|
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage
|
||||||
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
||||||
import org.session.libsignal.utilities.Hex
|
import org.session.libsignal.utilities.Hex
|
||||||
import org.session.libsignal.utilities.logging.Log
|
import org.session.libsignal.utilities.logging.Log
|
||||||
@ -72,8 +73,8 @@ object MultiDeviceProtocol {
|
|||||||
for (closedGroup in configurationMessage.closedGroups) {
|
for (closedGroup in configurationMessage.closedGroups) {
|
||||||
if (allClosedGroupPublicKeys.contains(closedGroup.publicKey)) continue
|
if (allClosedGroupPublicKeys.contains(closedGroup.publicKey)) continue
|
||||||
|
|
||||||
val closedGroupUpdate = SignalServiceProtos.ClosedGroupUpdateV2.newBuilder()
|
val closedGroupUpdate = DataMessage.ClosedGroupControlMessage.newBuilder()
|
||||||
closedGroupUpdate.type = SignalServiceProtos.ClosedGroupUpdateV2.Type.NEW
|
closedGroupUpdate.type = DataMessage.ClosedGroupControlMessage.Type.NEW
|
||||||
closedGroupUpdate.publicKey = ByteString.copyFrom(Hex.fromStringCondensed(closedGroup.publicKey))
|
closedGroupUpdate.publicKey = ByteString.copyFrom(Hex.fromStringCondensed(closedGroup.publicKey))
|
||||||
closedGroupUpdate.name = closedGroup.name
|
closedGroupUpdate.name = closedGroup.name
|
||||||
val encryptionKeyPair = SignalServiceProtos.KeyPair.newBuilder()
|
val encryptionKeyPair = SignalServiceProtos.KeyPair.newBuilder()
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki.protocol
|
|
||||||
|
|
||||||
import com.google.protobuf.ByteString
|
|
||||||
import org.session.libsession.messaging.jobs.Data
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
|
||||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
|
|
||||||
import org.session.libsession.messaging.threads.Address
|
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job
|
|
||||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
|
||||||
import org.thoughtcrime.securesms.jobs.BaseJob
|
|
||||||
import org.session.libsignal.utilities.logging.Log
|
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional
|
|
||||||
import org.session.libsignal.service.api.push.SignalServiceAddress
|
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
|
||||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities
|
|
||||||
import java.io.IOException
|
|
||||||
import java.security.SecureRandom
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
class NullMessageSendJob private constructor(parameters: Parameters, private val publicKey: String) : BaseJob(parameters) {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val KEY = "NullMessageSendJob"
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(publicKey: String) : this(Parameters.Builder()
|
|
||||||
.addConstraint(NetworkConstraint.KEY)
|
|
||||||
.setQueue(KEY)
|
|
||||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
|
||||||
.setMaxAttempts(1)
|
|
||||||
.build(),
|
|
||||||
publicKey)
|
|
||||||
|
|
||||||
override fun serialize(): Data {
|
|
||||||
return Data.Builder().putString("publicKey", publicKey).build()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getFactoryKey(): String { return KEY }
|
|
||||||
|
|
||||||
public override fun onRun() {
|
|
||||||
val contentMessage = SignalServiceProtos.Content.newBuilder()
|
|
||||||
val nullMessage = SignalServiceProtos.NullMessage.newBuilder()
|
|
||||||
val sr = SecureRandom()
|
|
||||||
val paddingSize = sr.nextInt(512)
|
|
||||||
val padding = ByteArray(paddingSize)
|
|
||||||
sr.nextBytes(padding)
|
|
||||||
nullMessage.padding = ByteString.copyFrom(padding)
|
|
||||||
contentMessage.nullMessage = nullMessage.build()
|
|
||||||
val serializedContentMessage = contentMessage.build().toByteArray()
|
|
||||||
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
|
||||||
val address = SignalServiceAddress(publicKey)
|
|
||||||
val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false)
|
|
||||||
val udAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient)
|
|
||||||
val ttl = TTLUtilities.getTTL(TTLUtilities.MessageType.Ephemeral)
|
|
||||||
try {
|
|
||||||
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess,
|
|
||||||
Date().time, serializedContentMessage, false, ttl,
|
|
||||||
false, false, false, Optional.absent())
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.d("Loki", "Failed to send null message to: $publicKey due to error: $e.")
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onShouldRetry(e: Exception): Boolean {
|
|
||||||
// Disable since we have our own retrying
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCanceled() { }
|
|
||||||
|
|
||||||
class Factory : Job.Factory<NullMessageSendJob> {
|
|
||||||
|
|
||||||
override fun create(parameters: Parameters, data: Data): NullMessageSendJob {
|
|
||||||
try {
|
|
||||||
val publicKey = data.getString("publicKey")
|
|
||||||
return NullMessageSendJob(parameters, publicKey)
|
|
||||||
} catch (e: IOException) {
|
|
||||||
throw AssertionError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki.protocol
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import org.session.libsignal.utilities.logging.Log
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
|
||||||
import org.thoughtcrime.securesms.crypto.SecurityEvent
|
|
||||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
|
||||||
import org.thoughtcrime.securesms.loki.utilities.recipient
|
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender
|
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingEndSessionMessage
|
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
|
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
|
||||||
import org.session.libsignal.libsignal.loki.SessionResetStatus
|
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceContent
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
object SessionManagementProtocol {
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun startSessionReset(context: Context, publicKey: String) {
|
|
||||||
val recipient = recipient(context, publicKey)
|
|
||||||
if (recipient.isGroupRecipient) { return }
|
|
||||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
|
||||||
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
|
||||||
val devices = lokiThreadDB.getSessionRestoreDevices(threadID)
|
|
||||||
for (device in devices) {
|
|
||||||
val endSessionMessage = OutgoingEndSessionMessage(OutgoingTextMessage(recipient, "TERMINATE", 0, -1))
|
|
||||||
MessageSender.send(context, endSessionMessage, threadID, false, null)
|
|
||||||
}
|
|
||||||
val smsDB = DatabaseFactory.getSmsDatabase(context)
|
|
||||||
val infoMessage = OutgoingTextMessage(recipient, "", 0, 0)
|
|
||||||
val infoMessageID = smsDB.insertMessageOutbox(threadID, infoMessage, false, System.currentTimeMillis(), null)
|
|
||||||
if (infoMessageID > -1) {
|
|
||||||
smsDB.markAsSentLokiSessionRestorationRequest(infoMessageID)
|
|
||||||
}
|
|
||||||
lokiThreadDB.removeAllSessionRestoreDevices(threadID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @JvmStatic
|
|
||||||
// fun refreshSignedPreKey(context: Context) {
|
|
||||||
// if (TextSecurePreferences.isSignedPreKeyRegistered(context)) {
|
|
||||||
// Log.d("Loki", "Skipping signed pre key refresh; using existing signed pre key.")
|
|
||||||
// } else {
|
|
||||||
// Log.d("Loki", "Signed pre key refreshed successfully.")
|
|
||||||
// val identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context)
|
|
||||||
// PreKeyUtil.generateSignedPreKey(context, identityKeyPair, true)
|
|
||||||
// TextSecurePreferences.setSignedPreKeyRegistered(context, true)
|
|
||||||
// ApplicationContext.getInstance(context).jobManager.add(CleanPreKeysJob())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun shouldProcessSessionRequest(context: Context, publicKey: String, timestamp: Long): Boolean {
|
|
||||||
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
|
|
||||||
val sentTimestamp = apiDB.getSessionRequestSentTimestamp(publicKey) ?: 0
|
|
||||||
val processedTimestamp = apiDB.getSessionRequestProcessedTimestamp(publicKey) ?: 0
|
|
||||||
val restorationTimestamp = TextSecurePreferences.getRestorationTime(context)
|
|
||||||
return timestamp > sentTimestamp && timestamp > processedTimestamp && timestamp > restorationTimestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun handlePreKeyBundleMessageIfNeeded(context: Context, content: SignalServiceContent) {
|
|
||||||
val preKeyBundleMessage = content.preKeyBundleMessage.orNull() ?: return
|
|
||||||
val publicKey = content.sender
|
|
||||||
if (recipient(context, publicKey).isGroupRecipient) { return } // Should never occur
|
|
||||||
Log.d("Loki", "Received a pre key bundle from: $publicKey.")
|
|
||||||
if (!shouldProcessSessionRequest(context, publicKey, content.timestamp)) {
|
|
||||||
Log.d("Loki", "Ignoring session request from: $publicKey.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val registrationID = TextSecurePreferences.getLocalRegistrationId(context)
|
|
||||||
// val lokiPreKeyBundleDatabase = DatabaseFactory.getLokiPreKeyBundleDatabase(context)
|
|
||||||
val preKeyBundle = preKeyBundleMessage.getPreKeyBundle(registrationID)
|
|
||||||
// lokiPreKeyBundleDatabase.setPreKeyBundle(publicKey, preKeyBundle)
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).setSessionRequestProcessedTimestamp(publicKey, Date().time)
|
|
||||||
val job = NullMessageSendJob(publicKey)
|
|
||||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun handleEndSessionMessageIfNeeded(context: Context, content: SignalServiceContent) {
|
|
||||||
if (!content.dataMessage.isPresent || !content.dataMessage.get().isEndSession) { return }
|
|
||||||
val sessionStore = TextSecureSessionStore(context)
|
|
||||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
|
||||||
Log.d("Loki", "Received a session reset request from: ${content.sender}; archiving the session.")
|
|
||||||
sessionStore.archiveAllSessions(content.sender)
|
|
||||||
lokiThreadDB.setSessionResetStatus(content.sender, SessionResetStatus.REQUEST_RECEIVED)
|
|
||||||
Log.d("Loki", "Sending an ephemeral message back to: ${content.sender}.")
|
|
||||||
val job = NullMessageSendJob(content.sender)
|
|
||||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
|
||||||
SecurityEvent.broadcastSecurityUpdateEvent(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun triggerSessionRestorationUI(context: Context, publicKey: String, errorTimestamp: Long) {
|
|
||||||
val recipient = recipient(context, publicKey)
|
|
||||||
if (recipient.isGroupRecipient) { return }
|
|
||||||
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
|
||||||
DatabaseFactory.getLokiThreadDatabase(context).addSessionRestoreDevice(threadID, publicKey)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki.protocol
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
|
||||||
import org.session.libsession.messaging.threads.Address
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
|
|
||||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol
|
|
||||||
import org.session.libsignal.libsignal.loki.SessionResetStatus
|
|
||||||
import org.session.libsignal.libsignal.protocol.PreKeySignalMessage
|
|
||||||
|
|
||||||
class SessionResetImplementation(private val context: Context) : SessionResetProtocol {
|
|
||||||
|
|
||||||
override fun getSessionResetStatus(publicKey: String): SessionResetStatus {
|
|
||||||
return DatabaseFactory.getLokiThreadDatabase(context).getSessionResetStatus(publicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setSessionResetStatus(publicKey: String, sessionResetStatus: SessionResetStatus) {
|
|
||||||
return DatabaseFactory.getLokiThreadDatabase(context).setSessionResetStatus(publicKey, sessionResetStatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNewSessionAdopted(publicKey: String, oldSessionResetStatus: SessionResetStatus) {
|
|
||||||
if (oldSessionResetStatus == SessionResetStatus.IN_PROGRESS) {
|
|
||||||
val job = NullMessageSendJob(publicKey)
|
|
||||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
|
||||||
}
|
|
||||||
val smsDB = DatabaseFactory.getSmsDatabase(context)
|
|
||||||
val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false)
|
|
||||||
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
|
||||||
val infoMessage = OutgoingTextMessage(recipient, "", 0, 0)
|
|
||||||
val infoMessageID = smsDB.insertMessageOutbox(threadID, infoMessage, false, System.currentTimeMillis(), null)
|
|
||||||
if (infoMessageID > -1) {
|
|
||||||
smsDB.markAsLokiSessionRestorationDone(infoMessageID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun validatePreKeySignalMessage(publicKey: String, message: PreKeySignalMessage) {
|
|
||||||
// val preKeyRecord = DatabaseFactory.getLokiPreKeyRecordDatabase(context).getPreKeyRecord(publicKey) ?: return
|
|
||||||
// // TODO: Checking that the pre key record isn't null is causing issues when it shouldn't
|
|
||||||
// check(preKeyRecord.id == (message.preKeyId ?: -1)) { "Received a background message from an unknown source." }
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager
|
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager
|
||||||
|
|
||||||
object MentionManagerUtilities {
|
object MentionManagerUtilities {
|
||||||
|
|
||||||
|
@ -15,8 +15,6 @@ import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities.populat
|
|||||||
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities.highlightMentions
|
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities.highlightMentions
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.util.DateUtils
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
|
||||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class ConversationView : LinearLayout {
|
class ConversationView : LinearLayout {
|
||||||
|
@ -10,7 +10,7 @@ import android.widget.ListView
|
|||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.loki.utilities.toPx
|
import org.thoughtcrime.securesms.loki.utilities.toPx
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.session.libsignal.service.loki.protocol.mentions.Mention
|
import org.session.libsignal.service.loki.utilities.mentions.Mention
|
||||||
|
|
||||||
class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : ListView(context, attrs, defStyleAttr) {
|
class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : ListView(context, attrs, defStyleAttr) {
|
||||||
private var mentionCandidates = listOf<Mention>()
|
private var mentionCandidates = listOf<Mention>()
|
||||||
|
@ -10,7 +10,7 @@ import kotlinx.android.synthetic.main.view_mention_candidate.view.*
|
|||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI
|
import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI
|
||||||
import org.session.libsignal.service.loki.protocol.mentions.Mention
|
import org.session.libsignal.service.loki.utilities.mentions.Mention
|
||||||
|
|
||||||
class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : LinearLayout(context, attrs, defStyleAttr) {
|
class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : LinearLayout(context, attrs, defStyleAttr) {
|
||||||
var mentionCandidate = Mention("", "")
|
var mentionCandidate = Mention("", "")
|
||||||
|
@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.loki.utilities.AvatarPlaceholderGenerator
|
|||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager
|
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager
|
||||||
|
|
||||||
// TODO: Look into a better way of handling different sizes. Maybe an enum (with associated values) encapsulating the different modes?
|
// TODO: Look into a better way of handling different sizes. Maybe an enum (with associated values) encapsulating the different modes?
|
||||||
|
|
||||||
|
@ -83,7 +83,6 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
|
|||||||
Optional.absent(),
|
Optional.absent(),
|
||||||
Optional.absent(),
|
Optional.absent(),
|
||||||
Optional.absent(),
|
Optional.absent(),
|
||||||
Optional.absent(),
|
|
||||||
Optional.absent());
|
Optional.absent());
|
||||||
|
|
||||||
database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
|
database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
|
||||||
|
@ -278,6 +278,12 @@ message GroupContext {
|
|||||||
repeated string members = 4;
|
repeated string members = 4;
|
||||||
optional AttachmentPointer avatar = 5;
|
optional AttachmentPointer avatar = 5;
|
||||||
repeated string admins = 6;
|
repeated string admins = 6;
|
||||||
|
|
||||||
|
// Loki - These fields are only used internally for the Android code base.
|
||||||
|
// This is so that we can differentiate adding/kicking.
|
||||||
|
// DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
repeated string newMembers = 998;
|
||||||
|
repeated string removedMembers = 999;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ContactDetails {
|
message ContactDetails {
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
package org.session.libsignal.libsignal.loki
|
|
||||||
|
|
||||||
import org.session.libsignal.libsignal.DecryptionCallback
|
|
||||||
import org.session.libsignal.libsignal.SessionCipher
|
|
||||||
import org.session.libsignal.libsignal.SignalProtocolAddress
|
|
||||||
import org.session.libsignal.libsignal.protocol.PreKeySignalMessage
|
|
||||||
import org.session.libsignal.libsignal.protocol.SignalMessage
|
|
||||||
import org.session.libsignal.libsignal.state.SessionState
|
|
||||||
import org.session.libsignal.libsignal.state.SignalProtocolStore
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper class for `SessionCipher`.
|
|
||||||
* This applies session reset logic on decryption.
|
|
||||||
*/
|
|
||||||
class LokiSessionCipher(private val protocolStore: SignalProtocolStore, private var sessionResetProtocol: SessionResetProtocol, val address: SignalProtocolAddress) : SessionCipher(protocolStore, address) {
|
|
||||||
|
|
||||||
override fun decrypt(ciphertext: PreKeySignalMessage?, callback: DecryptionCallback?): ByteArray {
|
|
||||||
// Record the current session state as it may change during decryption
|
|
||||||
val activeSession = getCurrentSessionState()
|
|
||||||
if (activeSession == null && ciphertext != null) {
|
|
||||||
sessionResetProtocol.validatePreKeySignalMessage(address.name, ciphertext)
|
|
||||||
}
|
|
||||||
val plainText = super.decrypt(ciphertext, callback)
|
|
||||||
handleSessionResetRequestIfNeeded(activeSession)
|
|
||||||
return plainText
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun decrypt(ciphertext: SignalMessage?, callback: DecryptionCallback?): ByteArray {
|
|
||||||
// Record the current session state as it may change during decryption
|
|
||||||
val activeSession = getCurrentSessionState()
|
|
||||||
val plainText = super.decrypt(ciphertext, callback)
|
|
||||||
handleSessionResetRequestIfNeeded(activeSession)
|
|
||||||
return plainText
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCurrentSessionState(): SessionState? {
|
|
||||||
val sessionRecord = protocolStore.loadSession(address)
|
|
||||||
return sessionRecord.sessionState
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleSessionResetRequestIfNeeded(oldSession: SessionState?) {
|
|
||||||
if (oldSession == null) { return }
|
|
||||||
val publicKey = address.name
|
|
||||||
val currentSessionResetStatus = sessionResetProtocol.getSessionResetStatus(publicKey)
|
|
||||||
if (currentSessionResetStatus == SessionResetStatus.NONE) return
|
|
||||||
val currentSession = getCurrentSessionState()
|
|
||||||
if (currentSession == null || currentSession.aliceBaseKey?.contentEquals(oldSession.aliceBaseKey) != true) {
|
|
||||||
if (currentSessionResetStatus == SessionResetStatus.REQUEST_RECEIVED) {
|
|
||||||
// The other user used an old session to contact us; wait for them to switch to a new one.
|
|
||||||
restoreSession(oldSession)
|
|
||||||
} else {
|
|
||||||
// Our session reset was successful; we initiated one and got a new session back from the other user.
|
|
||||||
deleteAllSessionsExcept(currentSession)
|
|
||||||
sessionResetProtocol.setSessionResetStatus(publicKey, SessionResetStatus.NONE)
|
|
||||||
sessionResetProtocol.onNewSessionAdopted(publicKey, currentSessionResetStatus)
|
|
||||||
}
|
|
||||||
} else if (currentSessionResetStatus == SessionResetStatus.REQUEST_RECEIVED) {
|
|
||||||
// Our session reset was successful; we received a message with the same session from the other user.
|
|
||||||
deleteAllSessionsExcept(oldSession)
|
|
||||||
sessionResetProtocol.setSessionResetStatus(publicKey, SessionResetStatus.NONE)
|
|
||||||
sessionResetProtocol.onNewSessionAdopted(publicKey, currentSessionResetStatus)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun restoreSession(state: SessionState) {
|
|
||||||
val session = protocolStore.loadSession(address)
|
|
||||||
session.previousSessionStates.removeAll { it.aliceBaseKey?.contentEquals(state.aliceBaseKey) ?: false }
|
|
||||||
session.promoteState(state)
|
|
||||||
protocolStore.storeSession(address, session)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deleteAllSessionsExcept(state: SessionState?) {
|
|
||||||
val sessionRecord = protocolStore.loadSession(address)
|
|
||||||
sessionRecord.removePreviousSessionStates()
|
|
||||||
sessionRecord.setState(state ?: SessionState())
|
|
||||||
protocolStore.storeSession(address, sessionRecord)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package org.session.libsignal.libsignal.loki
|
|
||||||
|
|
||||||
import org.session.libsignal.libsignal.protocol.PreKeySignalMessage
|
|
||||||
|
|
||||||
interface SessionResetProtocol {
|
|
||||||
|
|
||||||
fun getSessionResetStatus(publicKey: String): SessionResetStatus
|
|
||||||
fun setSessionResetStatus(publicKey: String, sessionResetStatus: SessionResetStatus)
|
|
||||||
fun validatePreKeySignalMessage(publicKey: String, message: PreKeySignalMessage)
|
|
||||||
fun onNewSessionAdopted(publicKey: String, oldSessionResetStatus: SessionResetStatus)
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package org.session.libsignal.libsignal.loki
|
|
||||||
|
|
||||||
enum class SessionResetStatus(val rawValue: Int) {
|
|
||||||
NONE(0),
|
|
||||||
IN_PROGRESS(1),
|
|
||||||
REQUEST_RECEIVED(2)
|
|
||||||
}
|
|
@ -24,8 +24,6 @@ import org.session.libsignal.libsignal.ecc.ECPrivateKey;
|
|||||||
import org.session.libsignal.libsignal.ecc.ECPublicKey;
|
import org.session.libsignal.libsignal.ecc.ECPublicKey;
|
||||||
import org.session.libsignal.libsignal.kdf.HKDFv3;
|
import org.session.libsignal.libsignal.kdf.HKDFv3;
|
||||||
import org.session.libsignal.libsignal.loki.FallbackSessionCipher;
|
import org.session.libsignal.libsignal.loki.FallbackSessionCipher;
|
||||||
import org.session.libsignal.libsignal.loki.LokiSessionCipher;
|
|
||||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol;
|
|
||||||
import org.session.libsignal.libsignal.protocol.CiphertextMessage;
|
import org.session.libsignal.libsignal.protocol.CiphertextMessage;
|
||||||
import org.session.libsignal.libsignal.protocol.PreKeySignalMessage;
|
import org.session.libsignal.libsignal.protocol.PreKeySignalMessage;
|
||||||
import org.session.libsignal.libsignal.protocol.SignalMessage;
|
import org.session.libsignal.libsignal.protocol.SignalMessage;
|
||||||
@ -51,15 +49,11 @@ import javax.crypto.spec.SecretKeySpec;
|
|||||||
public class SealedSessionCipher {
|
public class SealedSessionCipher {
|
||||||
|
|
||||||
private final SignalProtocolStore signalProtocolStore;
|
private final SignalProtocolStore signalProtocolStore;
|
||||||
private final SessionResetProtocol sessionResetProtocol;
|
|
||||||
private final SignalProtocolAddress localAddress;
|
private final SignalProtocolAddress localAddress;
|
||||||
|
|
||||||
public SealedSessionCipher(SignalProtocolStore signalProtocolStore,
|
public SealedSessionCipher(SignalProtocolStore signalProtocolStore, SignalProtocolAddress localAddress)
|
||||||
SessionResetProtocol sessionResetProtocol,
|
|
||||||
SignalProtocolAddress localAddress)
|
|
||||||
{
|
{
|
||||||
this.signalProtocolStore = signalProtocolStore;
|
this.signalProtocolStore = signalProtocolStore;
|
||||||
this.sessionResetProtocol = sessionResetProtocol;
|
|
||||||
this.localAddress = localAddress;
|
this.localAddress = localAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,8 +195,8 @@ public class SealedSessionCipher {
|
|||||||
SignalProtocolAddress sender = new SignalProtocolAddress(message.getSenderCertificate().getSender(), message.getSenderCertificate().getSenderDeviceId());
|
SignalProtocolAddress sender = new SignalProtocolAddress(message.getSenderCertificate().getSender(), message.getSenderCertificate().getSenderDeviceId());
|
||||||
|
|
||||||
switch (message.getType()) {
|
switch (message.getType()) {
|
||||||
case CiphertextMessage.WHISPER_TYPE: return new LokiSessionCipher(signalProtocolStore, sessionResetProtocol, sender).decrypt(new SignalMessage(message.getContent()));
|
case CiphertextMessage.WHISPER_TYPE: return new SessionCipher(signalProtocolStore, sender).decrypt(new SignalMessage(message.getContent()));
|
||||||
case CiphertextMessage.PREKEY_TYPE: return new LokiSessionCipher(signalProtocolStore, sessionResetProtocol, sender).decrypt(new PreKeySignalMessage(message.getContent()));
|
case CiphertextMessage.PREKEY_TYPE: return new SessionCipher(signalProtocolStore, sender).decrypt(new PreKeySignalMessage(message.getContent()));
|
||||||
case CiphertextMessage.FALLBACK_MESSAGE_TYPE: {
|
case CiphertextMessage.FALLBACK_MESSAGE_TYPE: {
|
||||||
try {
|
try {
|
||||||
byte[] privateKey = signalProtocolStore.getIdentityKeyPair().getPrivateKey().serialize();
|
byte[] privateKey = signalProtocolStore.getIdentityKeyPair().getPrivateKey().serialize();
|
||||||
|
@ -6,12 +6,10 @@
|
|||||||
package org.session.libsignal.service.api;
|
package org.session.libsignal.service.api;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.session.libsignal.libsignal.ecc.ECKeyPair;
|
import org.session.libsignal.libsignal.ecc.ECKeyPair;
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol;
|
|
||||||
import org.session.libsignal.libsignal.state.SignalProtocolStore;
|
import org.session.libsignal.libsignal.state.SignalProtocolStore;
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.api.crypto.AttachmentCipherOutputStream;
|
import org.session.libsignal.service.api.crypto.AttachmentCipherOutputStream;
|
||||||
@ -67,24 +65,20 @@ import org.session.libsignal.service.loki.database.LokiOpenGroupDatabaseProtocol
|
|||||||
import org.session.libsignal.service.loki.database.LokiPreKeyBundleDatabaseProtocol;
|
import org.session.libsignal.service.loki.database.LokiPreKeyBundleDatabaseProtocol;
|
||||||
import org.session.libsignal.service.loki.database.LokiThreadDatabaseProtocol;
|
import org.session.libsignal.service.loki.database.LokiThreadDatabaseProtocol;
|
||||||
import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol;
|
import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol;
|
||||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||||
import org.session.libsignal.service.loki.protocol.sessionmanagement.SessionManagementProtocol;
|
|
||||||
import org.session.libsignal.service.loki.utilities.Broadcaster;
|
import org.session.libsignal.service.loki.utilities.Broadcaster;
|
||||||
import org.session.libsignal.service.loki.utilities.HexEncodingKt;
|
import org.session.libsignal.service.loki.utilities.HexEncodingKt;
|
||||||
import org.session.libsignal.service.loki.utilities.PlaintextOutputStreamFactory;
|
import org.session.libsignal.service.loki.utilities.PlaintextOutputStreamFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
@ -100,10 +94,8 @@ public class SignalServiceMessageSender {
|
|||||||
|
|
||||||
private static final String TAG = SignalServiceMessageSender.class.getSimpleName();
|
private static final String TAG = SignalServiceMessageSender.class.getSimpleName();
|
||||||
|
|
||||||
private final PushServiceSocket socket;
|
|
||||||
private final SignalProtocolStore store;
|
private final SignalProtocolStore store;
|
||||||
private final SignalServiceAddress localAddress;
|
private final SignalServiceAddress localAddress;
|
||||||
private final Optional<EventListener> eventListener;
|
|
||||||
|
|
||||||
private final AtomicReference<Optional<SignalServiceMessagePipe>> pipe;
|
private final AtomicReference<Optional<SignalServiceMessagePipe>> pipe;
|
||||||
private final AtomicReference<Optional<SignalServiceMessagePipe>> unidentifiedPipe;
|
private final AtomicReference<Optional<SignalServiceMessagePipe>> unidentifiedPipe;
|
||||||
@ -113,9 +105,7 @@ public class SignalServiceMessageSender {
|
|||||||
private final LokiAPIDatabaseProtocol apiDatabase;
|
private final LokiAPIDatabaseProtocol apiDatabase;
|
||||||
private final LokiThreadDatabaseProtocol threadDatabase;
|
private final LokiThreadDatabaseProtocol threadDatabase;
|
||||||
private final LokiMessageDatabaseProtocol messageDatabase;
|
private final LokiMessageDatabaseProtocol messageDatabase;
|
||||||
private final LokiPreKeyBundleDatabaseProtocol preKeyBundleDatabase;
|
|
||||||
private final SessionProtocol sessionProtocolImpl;
|
private final SessionProtocol sessionProtocolImpl;
|
||||||
private final SessionResetProtocol sessionResetImpl;
|
|
||||||
private final LokiUserDatabaseProtocol userDatabase;
|
private final LokiUserDatabaseProtocol userDatabase;
|
||||||
private final LokiOpenGroupDatabaseProtocol openGroupDatabase;
|
private final LokiOpenGroupDatabaseProtocol openGroupDatabase;
|
||||||
private final Broadcaster broadcaster;
|
private final Broadcaster broadcaster;
|
||||||
@ -123,65 +113,48 @@ public class SignalServiceMessageSender {
|
|||||||
/**
|
/**
|
||||||
* Construct a SignalServiceMessageSender.
|
* Construct a SignalServiceMessageSender.
|
||||||
*
|
*
|
||||||
* @param urls The URL of the Signal Service.
|
|
||||||
* @param user The Signal Service username (eg phone number).
|
* @param user The Signal Service username (eg phone number).
|
||||||
* @param password The Signal Service user password.
|
* @param password The Signal Service user password.
|
||||||
* @param store The SignalProtocolStore.
|
* @param store The SignalProtocolStore.
|
||||||
* @param eventListener An optional event listener, which fires whenever sessions are
|
|
||||||
* setup or torn down for a recipient.
|
|
||||||
*/
|
*/
|
||||||
public SignalServiceMessageSender(SignalServiceConfiguration urls,
|
public SignalServiceMessageSender(String user, String password,
|
||||||
String user, String password,
|
|
||||||
SignalProtocolStore store,
|
SignalProtocolStore store,
|
||||||
String userAgent,
|
|
||||||
Optional<SignalServiceMessagePipe> pipe,
|
Optional<SignalServiceMessagePipe> pipe,
|
||||||
Optional<SignalServiceMessagePipe> unidentifiedPipe,
|
Optional<SignalServiceMessagePipe> unidentifiedPipe,
|
||||||
Optional<EventListener> eventListener,
|
|
||||||
String userPublicKey,
|
String userPublicKey,
|
||||||
LokiAPIDatabaseProtocol apiDatabase,
|
LokiAPIDatabaseProtocol apiDatabase,
|
||||||
LokiThreadDatabaseProtocol threadDatabase,
|
LokiThreadDatabaseProtocol threadDatabase,
|
||||||
LokiMessageDatabaseProtocol messageDatabase,
|
LokiMessageDatabaseProtocol messageDatabase,
|
||||||
LokiPreKeyBundleDatabaseProtocol preKeyBundleDatabase,
|
|
||||||
SessionProtocol sessionProtocolImpl,
|
SessionProtocol sessionProtocolImpl,
|
||||||
SessionResetProtocol sessionResetImpl,
|
|
||||||
LokiUserDatabaseProtocol userDatabase,
|
LokiUserDatabaseProtocol userDatabase,
|
||||||
LokiOpenGroupDatabaseProtocol openGroupDatabase,
|
LokiOpenGroupDatabaseProtocol openGroupDatabase,
|
||||||
Broadcaster broadcaster)
|
Broadcaster broadcaster)
|
||||||
{
|
{
|
||||||
this(urls, new StaticCredentialsProvider(user, password, null), store, userAgent, pipe, unidentifiedPipe, eventListener, userPublicKey, apiDatabase, threadDatabase, messageDatabase, preKeyBundleDatabase, sessionProtocolImpl, sessionResetImpl, userDatabase, openGroupDatabase, broadcaster);
|
this(new StaticCredentialsProvider(user, password, null), store, pipe, unidentifiedPipe, userPublicKey, apiDatabase, threadDatabase, messageDatabase, sessionProtocolImpl, userDatabase, openGroupDatabase, broadcaster);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignalServiceMessageSender(SignalServiceConfiguration urls,
|
public SignalServiceMessageSender(CredentialsProvider credentialsProvider,
|
||||||
CredentialsProvider credentialsProvider,
|
|
||||||
SignalProtocolStore store,
|
SignalProtocolStore store,
|
||||||
String userAgent,
|
|
||||||
Optional<SignalServiceMessagePipe> pipe,
|
Optional<SignalServiceMessagePipe> pipe,
|
||||||
Optional<SignalServiceMessagePipe> unidentifiedPipe,
|
Optional<SignalServiceMessagePipe> unidentifiedPipe,
|
||||||
Optional<EventListener> eventListener,
|
|
||||||
String userPublicKey,
|
String userPublicKey,
|
||||||
LokiAPIDatabaseProtocol apiDatabase,
|
LokiAPIDatabaseProtocol apiDatabase,
|
||||||
LokiThreadDatabaseProtocol threadDatabase,
|
LokiThreadDatabaseProtocol threadDatabase,
|
||||||
LokiMessageDatabaseProtocol messageDatabase,
|
LokiMessageDatabaseProtocol messageDatabase,
|
||||||
LokiPreKeyBundleDatabaseProtocol preKeyBundleDatabase,
|
|
||||||
SessionProtocol sessionProtocolImpl,
|
SessionProtocol sessionProtocolImpl,
|
||||||
SessionResetProtocol sessionResetImpl,
|
|
||||||
LokiUserDatabaseProtocol userDatabase,
|
LokiUserDatabaseProtocol userDatabase,
|
||||||
LokiOpenGroupDatabaseProtocol openGroupDatabase,
|
LokiOpenGroupDatabaseProtocol openGroupDatabase,
|
||||||
Broadcaster broadcaster)
|
Broadcaster broadcaster)
|
||||||
{
|
{
|
||||||
this.socket = new PushServiceSocket(urls, credentialsProvider, userAgent);
|
|
||||||
this.store = store;
|
this.store = store;
|
||||||
this.localAddress = new SignalServiceAddress(credentialsProvider.getUser());
|
this.localAddress = new SignalServiceAddress(credentialsProvider.getUser());
|
||||||
this.pipe = new AtomicReference<>(pipe);
|
this.pipe = new AtomicReference<>(pipe);
|
||||||
this.unidentifiedPipe = new AtomicReference<>(unidentifiedPipe);
|
this.unidentifiedPipe = new AtomicReference<>(unidentifiedPipe);
|
||||||
this.eventListener = eventListener;
|
|
||||||
this.userPublicKey = userPublicKey;
|
this.userPublicKey = userPublicKey;
|
||||||
this.apiDatabase = apiDatabase;
|
this.apiDatabase = apiDatabase;
|
||||||
this.threadDatabase = threadDatabase;
|
this.threadDatabase = threadDatabase;
|
||||||
this.messageDatabase = messageDatabase;
|
this.messageDatabase = messageDatabase;
|
||||||
this.preKeyBundleDatabase = preKeyBundleDatabase;
|
|
||||||
this.sessionProtocolImpl = sessionProtocolImpl;
|
this.sessionProtocolImpl = sessionProtocolImpl;
|
||||||
this.sessionResetImpl = sessionResetImpl;
|
|
||||||
this.userDatabase = userDatabase;
|
this.userDatabase = userDatabase;
|
||||||
this.openGroupDatabase = openGroupDatabase;
|
this.openGroupDatabase = openGroupDatabase;
|
||||||
this.broadcaster = broadcaster;
|
this.broadcaster = broadcaster;
|
||||||
|
@ -10,31 +10,11 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
|||||||
|
|
||||||
import org.session.libsignal.libsignal.ecc.ECKeyPair;
|
import org.session.libsignal.libsignal.ecc.ECKeyPair;
|
||||||
import org.session.libsignal.metadata.InvalidMetadataMessageException;
|
import org.session.libsignal.metadata.InvalidMetadataMessageException;
|
||||||
import org.session.libsignal.metadata.InvalidMetadataVersionException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolDuplicateMessageException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolInvalidKeyException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolInvalidKeyIdException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolInvalidMessageException;
|
import org.session.libsignal.metadata.ProtocolInvalidMessageException;
|
||||||
import org.session.libsignal.metadata.ProtocolInvalidVersionException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolLegacyMessageException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolNoSessionException;
|
|
||||||
import org.session.libsignal.metadata.ProtocolUntrustedIdentityException;
|
|
||||||
import org.session.libsignal.metadata.SealedSessionCipher;
|
import org.session.libsignal.metadata.SealedSessionCipher;
|
||||||
import org.session.libsignal.metadata.SelfSendException;
|
|
||||||
import org.session.libsignal.libsignal.DuplicateMessageException;
|
|
||||||
import org.session.libsignal.libsignal.InvalidKeyException;
|
|
||||||
import org.session.libsignal.libsignal.InvalidKeyIdException;
|
|
||||||
import org.session.libsignal.libsignal.InvalidMessageException;
|
import org.session.libsignal.libsignal.InvalidMessageException;
|
||||||
import org.session.libsignal.libsignal.InvalidVersionException;
|
|
||||||
import org.session.libsignal.libsignal.LegacyMessageException;
|
|
||||||
import org.session.libsignal.libsignal.NoSessionException;
|
|
||||||
import org.session.libsignal.libsignal.SessionCipher;
|
import org.session.libsignal.libsignal.SessionCipher;
|
||||||
import org.session.libsignal.libsignal.SignalProtocolAddress;
|
import org.session.libsignal.libsignal.SignalProtocolAddress;
|
||||||
import org.session.libsignal.libsignal.UntrustedIdentityException;
|
|
||||||
import org.session.libsignal.libsignal.loki.LokiSessionCipher;
|
|
||||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol;
|
|
||||||
import org.session.libsignal.libsignal.protocol.PreKeySignalMessage;
|
|
||||||
import org.session.libsignal.libsignal.protocol.SignalMessage;
|
|
||||||
import org.session.libsignal.libsignal.state.SignalProtocolStore;
|
import org.session.libsignal.libsignal.state.SignalProtocolStore;
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceAttachment;
|
import org.session.libsignal.service.api.messages.SignalServiceAttachment;
|
||||||
@ -60,7 +40,6 @@ import org.session.libsignal.service.loki.api.crypto.SessionProtocol;
|
|||||||
import org.session.libsignal.service.loki.api.crypto.SessionProtocolUtilities;
|
import org.session.libsignal.service.loki.api.crypto.SessionProtocolUtilities;
|
||||||
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol;
|
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -77,19 +56,16 @@ public class SignalServiceCipher {
|
|||||||
private static final String TAG = SignalServiceCipher.class.getSimpleName();
|
private static final String TAG = SignalServiceCipher.class.getSimpleName();
|
||||||
|
|
||||||
private final SignalProtocolStore signalProtocolStore;
|
private final SignalProtocolStore signalProtocolStore;
|
||||||
private final SessionResetProtocol sessionResetProtocol;
|
|
||||||
private final SignalServiceAddress localAddress;
|
private final SignalServiceAddress localAddress;
|
||||||
private final SessionProtocol sessionProtocolImpl;
|
private final SessionProtocol sessionProtocolImpl;
|
||||||
private final LokiAPIDatabaseProtocol apiDB;
|
private final LokiAPIDatabaseProtocol apiDB;
|
||||||
|
|
||||||
public SignalServiceCipher(SignalServiceAddress localAddress,
|
public SignalServiceCipher(SignalServiceAddress localAddress,
|
||||||
SignalProtocolStore signalProtocolStore,
|
SignalProtocolStore signalProtocolStore,
|
||||||
SessionResetProtocol sessionResetProtocol,
|
|
||||||
SessionProtocol sessionProtocolImpl,
|
SessionProtocol sessionProtocolImpl,
|
||||||
LokiAPIDatabaseProtocol apiDB)
|
LokiAPIDatabaseProtocol apiDB)
|
||||||
{
|
{
|
||||||
this.signalProtocolStore = signalProtocolStore;
|
this.signalProtocolStore = signalProtocolStore;
|
||||||
this.sessionResetProtocol = sessionResetProtocol;
|
|
||||||
this.localAddress = localAddress;
|
this.localAddress = localAddress;
|
||||||
this.sessionProtocolImpl = sessionProtocolImpl;
|
this.sessionProtocolImpl = sessionProtocolImpl;
|
||||||
this.apiDB = apiDB;
|
this.apiDB = apiDB;
|
||||||
@ -160,8 +136,8 @@ public class SignalServiceCipher {
|
|||||||
protected Plaintext decrypt(SignalServiceEnvelope envelope, byte[] ciphertext) throws InvalidMetadataMessageException
|
protected Plaintext decrypt(SignalServiceEnvelope envelope, byte[] ciphertext) throws InvalidMetadataMessageException
|
||||||
{
|
{
|
||||||
SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.getSource(), envelope.getSourceDevice());
|
SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.getSource(), envelope.getSourceDevice());
|
||||||
SessionCipher sessionCipher = new LokiSessionCipher(signalProtocolStore, sessionResetProtocol, sourceAddress);
|
SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, sourceAddress);
|
||||||
SealedSessionCipher sealedSessionCipher = new SealedSessionCipher(signalProtocolStore, sessionResetProtocol, new SignalProtocolAddress(localAddress.getNumber(), 1));
|
SealedSessionCipher sealedSessionCipher = new SealedSessionCipher(signalProtocolStore, new SignalProtocolAddress(localAddress.getNumber(), 1));
|
||||||
|
|
||||||
byte[] paddedMessage;
|
byte[] paddedMessage;
|
||||||
Metadata metadata;
|
Metadata metadata;
|
||||||
|
@ -7,9 +7,7 @@
|
|||||||
package org.session.libsignal.service.api.messages;
|
package org.session.libsignal.service.api.messages;
|
||||||
|
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.api.messages.calls.SignalServiceCallMessage;
|
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos;
|
import org.session.libsignal.service.internal.push.SignalServiceProtos;
|
||||||
import org.session.libsignal.service.loki.protocol.sessionmanagement.PreKeyBundleMessage;
|
|
||||||
|
|
||||||
public class SignalServiceContent {
|
public class SignalServiceContent {
|
||||||
private final String sender;
|
private final String sender;
|
||||||
@ -24,7 +22,6 @@ public class SignalServiceContent {
|
|||||||
|
|
||||||
// Loki
|
// Loki
|
||||||
public Optional<SignalServiceProtos.Content> configurationMessageProto = Optional.absent();
|
public Optional<SignalServiceProtos.Content> configurationMessageProto = Optional.absent();
|
||||||
public Optional<PreKeyBundleMessage> preKeyBundleMessage = Optional.absent();
|
|
||||||
public Optional<String> senderDisplayName = Optional.absent();
|
public Optional<String> senderDisplayName = Optional.absent();
|
||||||
public Optional<String> senderProfilePictureURL = Optional.absent();
|
public Optional<String> senderProfilePictureURL = Optional.absent();
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import org.session.libsignal.libsignal.util.guava.Optional;
|
|||||||
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
||||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage.ClosedGroupControlMessage;
|
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage.ClosedGroupControlMessage;
|
||||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.session.libsignal.service.api.messages;
|
package org.session.libsignal.service.api.messages;
|
||||||
|
|
||||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||||
|
|
||||||
public class SignalServiceNullMessage {
|
public class SignalServiceNullMessage {
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package org.session.libsignal.service.api.messages;
|
package org.session.libsignal.service.api.messages;
|
||||||
|
|
||||||
|
|
||||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.session.libsignal.service.api.messages;
|
package org.session.libsignal.service.api.messages;
|
||||||
|
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
|
||||||
|
|
||||||
public class SignalServiceTypingMessage {
|
public class SignalServiceTypingMessage {
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package org.session.libsignal.service.api.messages.calls;
|
package org.session.libsignal.service.api.messages.calls;
|
||||||
|
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -24483,6 +24483,70 @@ public final class SignalServiceProtos {
|
|||||||
*/
|
*/
|
||||||
com.google.protobuf.ByteString
|
com.google.protobuf.ByteString
|
||||||
getAdminsBytes(int index);
|
getAdminsBytes(int index);
|
||||||
|
|
||||||
|
// repeated string newMembers = 998;
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
java.util.List<java.lang.String>
|
||||||
|
getNewMembersList();
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
int getNewMembersCount();
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
java.lang.String getNewMembers(int index);
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
com.google.protobuf.ByteString
|
||||||
|
getNewMembersBytes(int index);
|
||||||
|
|
||||||
|
// repeated string removedMembers = 999;
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
java.util.List<java.lang.String>
|
||||||
|
getRemovedMembersList();
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
int getRemovedMembersCount();
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
java.lang.String getRemovedMembers(int index);
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
com.google.protobuf.ByteString
|
||||||
|
getRemovedMembersBytes(int index);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Protobuf type {@code signalservice.GroupContext}
|
* Protobuf type {@code signalservice.GroupContext}
|
||||||
@ -24585,6 +24649,22 @@ public final class SignalServiceProtos {
|
|||||||
admins_.add(input.readBytes());
|
admins_.add(input.readBytes());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 7986: {
|
||||||
|
if (!((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
|
||||||
|
newMembers_ = new com.google.protobuf.LazyStringArrayList();
|
||||||
|
mutable_bitField0_ |= 0x00000040;
|
||||||
|
}
|
||||||
|
newMembers_.add(input.readBytes());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7994: {
|
||||||
|
if (!((mutable_bitField0_ & 0x00000080) == 0x00000080)) {
|
||||||
|
removedMembers_ = new com.google.protobuf.LazyStringArrayList();
|
||||||
|
mutable_bitField0_ |= 0x00000080;
|
||||||
|
}
|
||||||
|
removedMembers_.add(input.readBytes());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||||
@ -24599,6 +24679,12 @@ public final class SignalServiceProtos {
|
|||||||
if (((mutable_bitField0_ & 0x00000020) == 0x00000020)) {
|
if (((mutable_bitField0_ & 0x00000020) == 0x00000020)) {
|
||||||
admins_ = new com.google.protobuf.UnmodifiableLazyStringList(admins_);
|
admins_ = new com.google.protobuf.UnmodifiableLazyStringList(admins_);
|
||||||
}
|
}
|
||||||
|
if (((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
|
||||||
|
newMembers_ = new com.google.protobuf.UnmodifiableLazyStringList(newMembers_);
|
||||||
|
}
|
||||||
|
if (((mutable_bitField0_ & 0x00000080) == 0x00000080)) {
|
||||||
|
removedMembers_ = new com.google.protobuf.UnmodifiableLazyStringList(removedMembers_);
|
||||||
|
}
|
||||||
this.unknownFields = unknownFields.build();
|
this.unknownFields = unknownFields.build();
|
||||||
makeExtensionsImmutable();
|
makeExtensionsImmutable();
|
||||||
}
|
}
|
||||||
@ -24913,6 +24999,90 @@ public final class SignalServiceProtos {
|
|||||||
return admins_.getByteString(index);
|
return admins_.getByteString(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// repeated string newMembers = 998;
|
||||||
|
public static final int NEWMEMBERS_FIELD_NUMBER = 998;
|
||||||
|
private com.google.protobuf.LazyStringList newMembers_;
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public java.util.List<java.lang.String>
|
||||||
|
getNewMembersList() {
|
||||||
|
return newMembers_;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public int getNewMembersCount() {
|
||||||
|
return newMembers_.size();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public java.lang.String getNewMembers(int index) {
|
||||||
|
return newMembers_.get(index);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public com.google.protobuf.ByteString
|
||||||
|
getNewMembersBytes(int index) {
|
||||||
|
return newMembers_.getByteString(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// repeated string removedMembers = 999;
|
||||||
|
public static final int REMOVEDMEMBERS_FIELD_NUMBER = 999;
|
||||||
|
private com.google.protobuf.LazyStringList removedMembers_;
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public java.util.List<java.lang.String>
|
||||||
|
getRemovedMembersList() {
|
||||||
|
return removedMembers_;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public int getRemovedMembersCount() {
|
||||||
|
return removedMembers_.size();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public java.lang.String getRemovedMembers(int index) {
|
||||||
|
return removedMembers_.get(index);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public com.google.protobuf.ByteString
|
||||||
|
getRemovedMembersBytes(int index) {
|
||||||
|
return removedMembers_.getByteString(index);
|
||||||
|
}
|
||||||
|
|
||||||
private void initFields() {
|
private void initFields() {
|
||||||
id_ = com.google.protobuf.ByteString.EMPTY;
|
id_ = com.google.protobuf.ByteString.EMPTY;
|
||||||
type_ = org.session.libsignal.service.internal.push.SignalServiceProtos.GroupContext.Type.UNKNOWN;
|
type_ = org.session.libsignal.service.internal.push.SignalServiceProtos.GroupContext.Type.UNKNOWN;
|
||||||
@ -24920,6 +25090,8 @@ public final class SignalServiceProtos {
|
|||||||
members_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
members_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
avatar_ = org.session.libsignal.service.internal.push.SignalServiceProtos.AttachmentPointer.getDefaultInstance();
|
avatar_ = org.session.libsignal.service.internal.push.SignalServiceProtos.AttachmentPointer.getDefaultInstance();
|
||||||
admins_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
admins_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
|
newMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
|
removedMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
}
|
}
|
||||||
private byte memoizedIsInitialized = -1;
|
private byte memoizedIsInitialized = -1;
|
||||||
public final boolean isInitialized() {
|
public final boolean isInitialized() {
|
||||||
@ -24951,6 +25123,12 @@ public final class SignalServiceProtos {
|
|||||||
for (int i = 0; i < admins_.size(); i++) {
|
for (int i = 0; i < admins_.size(); i++) {
|
||||||
output.writeBytes(6, admins_.getByteString(i));
|
output.writeBytes(6, admins_.getByteString(i));
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < newMembers_.size(); i++) {
|
||||||
|
output.writeBytes(998, newMembers_.getByteString(i));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < removedMembers_.size(); i++) {
|
||||||
|
output.writeBytes(999, removedMembers_.getByteString(i));
|
||||||
|
}
|
||||||
getUnknownFields().writeTo(output);
|
getUnknownFields().writeTo(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24994,6 +25172,24 @@ public final class SignalServiceProtos {
|
|||||||
size += dataSize;
|
size += dataSize;
|
||||||
size += 1 * getAdminsList().size();
|
size += 1 * getAdminsList().size();
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
int dataSize = 0;
|
||||||
|
for (int i = 0; i < newMembers_.size(); i++) {
|
||||||
|
dataSize += com.google.protobuf.CodedOutputStream
|
||||||
|
.computeBytesSizeNoTag(newMembers_.getByteString(i));
|
||||||
|
}
|
||||||
|
size += dataSize;
|
||||||
|
size += 2 * getNewMembersList().size();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int dataSize = 0;
|
||||||
|
for (int i = 0; i < removedMembers_.size(); i++) {
|
||||||
|
dataSize += com.google.protobuf.CodedOutputStream
|
||||||
|
.computeBytesSizeNoTag(removedMembers_.getByteString(i));
|
||||||
|
}
|
||||||
|
size += dataSize;
|
||||||
|
size += 2 * getRemovedMembersList().size();
|
||||||
|
}
|
||||||
size += getUnknownFields().getSerializedSize();
|
size += getUnknownFields().getSerializedSize();
|
||||||
memoizedSerializedSize = size;
|
memoizedSerializedSize = size;
|
||||||
return size;
|
return size;
|
||||||
@ -25127,6 +25323,10 @@ public final class SignalServiceProtos {
|
|||||||
bitField0_ = (bitField0_ & ~0x00000010);
|
bitField0_ = (bitField0_ & ~0x00000010);
|
||||||
admins_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
admins_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
bitField0_ = (bitField0_ & ~0x00000020);
|
bitField0_ = (bitField0_ & ~0x00000020);
|
||||||
|
newMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000040);
|
||||||
|
removedMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000080);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25187,6 +25387,18 @@ public final class SignalServiceProtos {
|
|||||||
bitField0_ = (bitField0_ & ~0x00000020);
|
bitField0_ = (bitField0_ & ~0x00000020);
|
||||||
}
|
}
|
||||||
result.admins_ = admins_;
|
result.admins_ = admins_;
|
||||||
|
if (((bitField0_ & 0x00000040) == 0x00000040)) {
|
||||||
|
newMembers_ = new com.google.protobuf.UnmodifiableLazyStringList(
|
||||||
|
newMembers_);
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000040);
|
||||||
|
}
|
||||||
|
result.newMembers_ = newMembers_;
|
||||||
|
if (((bitField0_ & 0x00000080) == 0x00000080)) {
|
||||||
|
removedMembers_ = new com.google.protobuf.UnmodifiableLazyStringList(
|
||||||
|
removedMembers_);
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000080);
|
||||||
|
}
|
||||||
|
result.removedMembers_ = removedMembers_;
|
||||||
result.bitField0_ = to_bitField0_;
|
result.bitField0_ = to_bitField0_;
|
||||||
onBuilt();
|
onBuilt();
|
||||||
return result;
|
return result;
|
||||||
@ -25237,6 +25449,26 @@ public final class SignalServiceProtos {
|
|||||||
}
|
}
|
||||||
onChanged();
|
onChanged();
|
||||||
}
|
}
|
||||||
|
if (!other.newMembers_.isEmpty()) {
|
||||||
|
if (newMembers_.isEmpty()) {
|
||||||
|
newMembers_ = other.newMembers_;
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000040);
|
||||||
|
} else {
|
||||||
|
ensureNewMembersIsMutable();
|
||||||
|
newMembers_.addAll(other.newMembers_);
|
||||||
|
}
|
||||||
|
onChanged();
|
||||||
|
}
|
||||||
|
if (!other.removedMembers_.isEmpty()) {
|
||||||
|
if (removedMembers_.isEmpty()) {
|
||||||
|
removedMembers_ = other.removedMembers_;
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000080);
|
||||||
|
} else {
|
||||||
|
ensureRemovedMembersIsMutable();
|
||||||
|
removedMembers_.addAll(other.removedMembers_);
|
||||||
|
}
|
||||||
|
onChanged();
|
||||||
|
}
|
||||||
this.mergeUnknownFields(other.getUnknownFields());
|
this.mergeUnknownFields(other.getUnknownFields());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -25745,6 +25977,246 @@ public final class SignalServiceProtos {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// repeated string newMembers = 998;
|
||||||
|
private com.google.protobuf.LazyStringList newMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
|
private void ensureNewMembersIsMutable() {
|
||||||
|
if (!((bitField0_ & 0x00000040) == 0x00000040)) {
|
||||||
|
newMembers_ = new com.google.protobuf.LazyStringArrayList(newMembers_);
|
||||||
|
bitField0_ |= 0x00000040;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public java.util.List<java.lang.String>
|
||||||
|
getNewMembersList() {
|
||||||
|
return java.util.Collections.unmodifiableList(newMembers_);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public int getNewMembersCount() {
|
||||||
|
return newMembers_.size();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public java.lang.String getNewMembers(int index) {
|
||||||
|
return newMembers_.get(index);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public com.google.protobuf.ByteString
|
||||||
|
getNewMembersBytes(int index) {
|
||||||
|
return newMembers_.getByteString(index);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public Builder setNewMembers(
|
||||||
|
int index, java.lang.String value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
ensureNewMembersIsMutable();
|
||||||
|
newMembers_.set(index, value);
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public Builder addNewMembers(
|
||||||
|
java.lang.String value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
ensureNewMembersIsMutable();
|
||||||
|
newMembers_.add(value);
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public Builder addAllNewMembers(
|
||||||
|
java.lang.Iterable<java.lang.String> values) {
|
||||||
|
ensureNewMembersIsMutable();
|
||||||
|
super.addAll(values, newMembers_);
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public Builder clearNewMembers() {
|
||||||
|
newMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000040);
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string newMembers = 998;</code>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Loki - These fields are only used internally for the Android code base.
|
||||||
|
* This is so that we can differentiate adding/kicking.
|
||||||
|
* DO NOT USE WHEN SENDING MESSAGES.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public Builder addNewMembersBytes(
|
||||||
|
com.google.protobuf.ByteString value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
ensureNewMembersIsMutable();
|
||||||
|
newMembers_.add(value);
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// repeated string removedMembers = 999;
|
||||||
|
private com.google.protobuf.LazyStringList removedMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
|
private void ensureRemovedMembersIsMutable() {
|
||||||
|
if (!((bitField0_ & 0x00000080) == 0x00000080)) {
|
||||||
|
removedMembers_ = new com.google.protobuf.LazyStringArrayList(removedMembers_);
|
||||||
|
bitField0_ |= 0x00000080;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public java.util.List<java.lang.String>
|
||||||
|
getRemovedMembersList() {
|
||||||
|
return java.util.Collections.unmodifiableList(removedMembers_);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public int getRemovedMembersCount() {
|
||||||
|
return removedMembers_.size();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public java.lang.String getRemovedMembers(int index) {
|
||||||
|
return removedMembers_.get(index);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public com.google.protobuf.ByteString
|
||||||
|
getRemovedMembersBytes(int index) {
|
||||||
|
return removedMembers_.getByteString(index);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public Builder setRemovedMembers(
|
||||||
|
int index, java.lang.String value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
ensureRemovedMembersIsMutable();
|
||||||
|
removedMembers_.set(index, value);
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public Builder addRemovedMembers(
|
||||||
|
java.lang.String value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
ensureRemovedMembersIsMutable();
|
||||||
|
removedMembers_.add(value);
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public Builder addAllRemovedMembers(
|
||||||
|
java.lang.Iterable<java.lang.String> values) {
|
||||||
|
ensureRemovedMembersIsMutable();
|
||||||
|
super.addAll(values, removedMembers_);
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public Builder clearRemovedMembers() {
|
||||||
|
removedMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000080);
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <code>repeated string removedMembers = 999;</code>
|
||||||
|
*/
|
||||||
|
public Builder addRemovedMembersBytes(
|
||||||
|
com.google.protobuf.ByteString value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
ensureRemovedMembersIsMutable();
|
||||||
|
removedMembers_.add(value);
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// @@protoc_insertion_point(builder_scope:signalservice.GroupContext)
|
// @@protoc_insertion_point(builder_scope:signalservice.GroupContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30486,28 +30958,30 @@ public final class SignalServiceProtos {
|
|||||||
"thumbnail\030\005 \001(\014\022\016\n\006digest\030\006 \001(\014\022\020\n\010fileN" +
|
"thumbnail\030\005 \001(\014\022\016\n\006digest\030\006 \001(\014\022\020\n\010fileN" +
|
||||||
"ame\030\007 \001(\t\022\r\n\005flags\030\010 \001(\r\022\r\n\005width\030\t \001(\r\022" +
|
"ame\030\007 \001(\t\022\r\n\005flags\030\010 \001(\r\022\r\n\005width\030\t \001(\r\022" +
|
||||||
"\016\n\006height\030\n \001(\r\022\017\n\007caption\030\013 \001(\t\022\013\n\003url\030",
|
"\016\n\006height\030\n \001(\r\022\017\n\007caption\030\013 \001(\t\022\013\n\003url\030",
|
||||||
"e \001(\t\"\032\n\005Flags\022\021\n\rVOICE_MESSAGE\020\001\"\365\001\n\014Gr" +
|
"e \001(\t\"\032\n\005Flags\022\021\n\rVOICE_MESSAGE\020\001\"\243\002\n\014Gr" +
|
||||||
"oupContext\022\n\n\002id\030\001 \001(\014\022.\n\004type\030\002 \001(\0162 .s" +
|
"oupContext\022\n\n\002id\030\001 \001(\014\022.\n\004type\030\002 \001(\0162 .s" +
|
||||||
"ignalservice.GroupContext.Type\022\014\n\004name\030\003" +
|
"ignalservice.GroupContext.Type\022\014\n\004name\030\003" +
|
||||||
" \001(\t\022\017\n\007members\030\004 \003(\t\0220\n\006avatar\030\005 \001(\0132 ." +
|
" \001(\t\022\017\n\007members\030\004 \003(\t\0220\n\006avatar\030\005 \001(\0132 ." +
|
||||||
"signalservice.AttachmentPointer\022\016\n\006admin" +
|
"signalservice.AttachmentPointer\022\016\n\006admin" +
|
||||||
"s\030\006 \003(\t\"H\n\004Type\022\013\n\007UNKNOWN\020\000\022\n\n\006UPDATE\020\001" +
|
"s\030\006 \003(\t\022\023\n\nnewMembers\030\346\007 \003(\t\022\027\n\016removedM" +
|
||||||
"\022\013\n\007DELIVER\020\002\022\010\n\004QUIT\020\003\022\020\n\014REQUEST_INFO\020" +
|
"embers\030\347\007 \003(\t\"H\n\004Type\022\013\n\007UNKNOWN\020\000\022\n\n\006UP" +
|
||||||
"\004\"\356\001\n\016ContactDetails\022\016\n\006number\030\001 \001(\t\022\014\n\004" +
|
"DATE\020\001\022\013\n\007DELIVER\020\002\022\010\n\004QUIT\020\003\022\020\n\014REQUEST" +
|
||||||
"name\030\002 \001(\t\0224\n\006avatar\030\003 \001(\0132$.signalservi" +
|
"_INFO\020\004\"\356\001\n\016ContactDetails\022\016\n\006number\030\001 \001" +
|
||||||
"ce.ContactDetails.Avatar\022\r\n\005color\030\004 \001(\t\022",
|
"(\t\022\014\n\004name\030\002 \001(\t\0224\n\006avatar\030\003 \001(\0132$.signa",
|
||||||
"\022\n\nprofileKey\030\006 \001(\014\022\017\n\007blocked\030\007 \001(\010\022\023\n\013" +
|
"lservice.ContactDetails.Avatar\022\r\n\005color\030" +
|
||||||
"expireTimer\030\010 \001(\r\022\020\n\010nickname\030e \001(\t\032-\n\006A" +
|
"\004 \001(\t\022\022\n\nprofileKey\030\006 \001(\014\022\017\n\007blocked\030\007 \001" +
|
||||||
"vatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006length\030\002 \001" +
|
"(\010\022\023\n\013expireTimer\030\010 \001(\r\022\020\n\010nickname\030e \001(" +
|
||||||
"(\r\"\367\001\n\014GroupDetails\022\n\n\002id\030\001 \001(\014\022\014\n\004name\030" +
|
"\t\032-\n\006Avatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006leng" +
|
||||||
"\002 \001(\t\022\017\n\007members\030\003 \003(\t\0222\n\006avatar\030\004 \001(\0132\"" +
|
"th\030\002 \001(\r\"\367\001\n\014GroupDetails\022\n\n\002id\030\001 \001(\014\022\014\n" +
|
||||||
".signalservice.GroupDetails.Avatar\022\024\n\006ac" +
|
"\004name\030\002 \001(\t\022\017\n\007members\030\003 \003(\t\0222\n\006avatar\030\004" +
|
||||||
"tive\030\005 \001(\010:\004true\022\023\n\013expireTimer\030\006 \001(\r\022\r\n" +
|
" \001(\0132\".signalservice.GroupDetails.Avatar" +
|
||||||
"\005color\030\007 \001(\t\022\017\n\007blocked\030\010 \001(\010\022\016\n\006admins\030" +
|
"\022\024\n\006active\030\005 \001(\010:\004true\022\023\n\013expireTimer\030\006 " +
|
||||||
"\t \003(\t\032-\n\006Avatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006" +
|
"\001(\r\022\r\n\005color\030\007 \001(\t\022\017\n\007blocked\030\010 \001(\010\022\016\n\006a" +
|
||||||
"length\030\002 \001(\r\"\"\n\016PublicChatInfo\022\020\n\010server",
|
"dmins\030\t \003(\t\032-\n\006Avatar\022\023\n\013contentType\030\001 \001",
|
||||||
"ID\030\001 \001(\004BB\n+org.session.libsignal.servic" +
|
"(\t\022\016\n\006length\030\002 \001(\r\"\"\n\016PublicChatInfo\022\020\n\010" +
|
||||||
"e.internal.pushB\023SignalServiceProtos"
|
"serverID\030\001 \001(\004BB\n+org.session.libsignal." +
|
||||||
|
"service.internal.pushB\023SignalServiceProt" +
|
||||||
|
"os"
|
||||||
};
|
};
|
||||||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||||
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
||||||
@ -30651,7 +31125,7 @@ public final class SignalServiceProtos {
|
|||||||
internal_static_signalservice_GroupContext_fieldAccessorTable = new
|
internal_static_signalservice_GroupContext_fieldAccessorTable = new
|
||||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||||
internal_static_signalservice_GroupContext_descriptor,
|
internal_static_signalservice_GroupContext_descriptor,
|
||||||
new java.lang.String[] { "Id", "Type", "Name", "Members", "Avatar", "Admins", });
|
new java.lang.String[] { "Id", "Type", "Name", "Members", "Avatar", "Admins", "NewMembers", "RemovedMembers", });
|
||||||
internal_static_signalservice_ContactDetails_descriptor =
|
internal_static_signalservice_ContactDetails_descriptor =
|
||||||
getDescriptor().getMessageTypes().get(10);
|
getDescriptor().getMessageTypes().get(10);
|
||||||
internal_static_signalservice_ContactDetails_fieldAccessorTable = new
|
internal_static_signalservice_ContactDetails_fieldAccessorTable = new
|
||||||
|
@ -5,7 +5,7 @@ import nl.komponents.kovenant.deferred
|
|||||||
import org.session.libsignal.utilities.logging.Log
|
import org.session.libsignal.utilities.logging.Log
|
||||||
import org.session.libsignal.utilities.Base64
|
import org.session.libsignal.utilities.Base64
|
||||||
import org.session.libsignal.service.loki.api.crypto.ProofOfWork
|
import org.session.libsignal.service.loki.api.crypto.ProofOfWork
|
||||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities
|
import org.session.libsignal.service.loki.utilities.TTLUtilities
|
||||||
import org.session.libsignal.utilities.ThreadUtils
|
import org.session.libsignal.utilities.ThreadUtils
|
||||||
import org.session.libsignal.service.loki.utilities.prettifiedDescription
|
import org.session.libsignal.service.loki.utilities.prettifiedDescription
|
||||||
|
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
package org.session.libsignal.service.loki.protocol.meta
|
|
||||||
|
|
||||||
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
|
|
||||||
|
|
||||||
public class SessionMetaProtocol(private val apiDatabase: LokiAPIDatabaseProtocol, private val userPublicKey: String) {
|
|
||||||
|
|
||||||
// region Initialization
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
public lateinit var shared: SessionMetaProtocol
|
|
||||||
|
|
||||||
public fun configureIfNeeded(apiDatabase: LokiAPIDatabaseProtocol, userPublicKey: String) {
|
|
||||||
if (::shared.isInitialized) { return; }
|
|
||||||
shared = SessionMetaProtocol(apiDatabase, userPublicKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Utilities
|
|
||||||
public fun isNoteToSelf(publicKey: String): Boolean {
|
|
||||||
return userPublicKey == publicKey // return MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey).contains(publicKey)
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
package org.session.libsignal.service.loki.protocol.sessionmanagement
|
|
||||||
|
|
||||||
import org.session.libsignal.libsignal.IdentityKey
|
|
||||||
import org.session.libsignal.libsignal.ecc.Curve
|
|
||||||
import org.session.libsignal.libsignal.state.PreKeyBundle
|
|
||||||
|
|
||||||
data class PreKeyBundleMessage(
|
|
||||||
val identityKey: ByteArray,
|
|
||||||
val deviceID: Int,
|
|
||||||
val preKeyID: Int,
|
|
||||||
val signedPreKeyID: Int,
|
|
||||||
val preKey: ByteArray,
|
|
||||||
val signedPreKey: ByteArray,
|
|
||||||
val signedPreKeySignature: ByteArray
|
|
||||||
) {
|
|
||||||
|
|
||||||
constructor(preKeyBundle: PreKeyBundle) : this(preKeyBundle.identityKey.serialize(), preKeyBundle.deviceId, preKeyBundle.preKeyId,
|
|
||||||
preKeyBundle.signedPreKeyId, preKeyBundle.preKey.serialize(), preKeyBundle.signedPreKey.serialize(), preKeyBundle.signedPreKeySignature)
|
|
||||||
|
|
||||||
fun getPreKeyBundle(registrationID: Int): PreKeyBundle {
|
|
||||||
return PreKeyBundle(registrationID, deviceID, preKeyID, Curve.decodePoint(preKey, 0), signedPreKeyID, Curve.decodePoint(signedPreKey, 0), signedPreKeySignature, IdentityKey(identityKey, 0))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package org.session.libsignal.service.loki.protocol.sessionmanagement
|
|
||||||
|
|
||||||
import org.session.libsignal.utilities.logging.Log
|
|
||||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol
|
|
||||||
import org.session.libsignal.libsignal.loki.SessionResetStatus
|
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional
|
|
||||||
import org.session.libsignal.service.api.SignalServiceMessageSender
|
|
||||||
import org.session.libsignal.service.api.push.SignalServiceAddress
|
|
||||||
|
|
||||||
public class SessionManagementProtocol(private val sessionResetImpl: SessionResetProtocol, private val delegate: SessionManagementProtocolDelegate) {
|
|
||||||
|
|
||||||
// region Initialization
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
public lateinit var shared: SessionManagementProtocol
|
|
||||||
|
|
||||||
public fun configureIfNeeded(sessionResetImpl: SessionResetProtocol, delegate: SessionManagementProtocolDelegate) {
|
|
||||||
if (::shared.isInitialized) { return; }
|
|
||||||
shared = SessionManagementProtocol(sessionResetImpl, delegate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
|
|
||||||
// region Sending
|
|
||||||
/**
|
|
||||||
* Called after an end session message is sent.
|
|
||||||
*/
|
|
||||||
public fun setSessionResetStatusToInProgressIfNeeded(recipient: SignalServiceAddress, eventListener: Optional<SignalServiceMessageSender.EventListener>) {
|
|
||||||
val publicKey = recipient.number
|
|
||||||
val sessionResetStatus = sessionResetImpl.getSessionResetStatus(publicKey)
|
|
||||||
if (sessionResetStatus == SessionResetStatus.REQUEST_RECEIVED) { return }
|
|
||||||
Log.d("Loki", "Starting session reset")
|
|
||||||
sessionResetImpl.setSessionResetStatus(publicKey, SessionResetStatus.IN_PROGRESS)
|
|
||||||
if (!eventListener.isPresent) { return }
|
|
||||||
eventListener.get().onSecurityEvent(recipient)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun repairSessionIfNeeded(recipient: SignalServiceAddress, isClosedGroup: Boolean) {
|
|
||||||
val publicKey = recipient.number
|
|
||||||
if (!isClosedGroup) { return }
|
|
||||||
delegate.sendSessionRequestIfNeeded(publicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun shouldIgnoreMissingPreKeyBundleException(isClosedGroup: Boolean): Boolean {
|
|
||||||
// When a closed group is created, members try to establish sessions with eachother in the background through
|
|
||||||
// session requests. Until ALL users those session requests were sent to have come online, stored the pre key
|
|
||||||
// bundles contained in the session requests and replied with background messages to finalize the session
|
|
||||||
// creation, a given user won't be able to successfully send a message to all members of a group. This check
|
|
||||||
// is so that until we can do better on this front the user at least won't see this as an error in the UI.
|
|
||||||
return isClosedGroup
|
|
||||||
}
|
|
||||||
// endregion
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package org.session.libsignal.service.loki.protocol.sessionmanagement
|
|
||||||
|
|
||||||
interface SessionManagementProtocolDelegate {
|
|
||||||
|
|
||||||
fun sendSessionRequestIfNeeded(publicKey: String)
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package org.session.libsignal.service.loki.protocol.meta
|
package org.session.libsignal.service.loki.utilities
|
||||||
|
|
||||||
public object TTLUtilities {
|
public object TTLUtilities {
|
||||||
|
|
@ -1,3 +1,3 @@
|
|||||||
package org.session.libsignal.service.loki.protocol.mentions
|
package org.session.libsignal.service.loki.utilities.mentions
|
||||||
|
|
||||||
data class Mention(val publicKey: String, val displayName: String)
|
data class Mention(val publicKey: String, val displayName: String)
|
@ -1,4 +1,4 @@
|
|||||||
package org.session.libsignal.service.loki.protocol.mentions
|
package org.session.libsignal.service.loki.utilities.mentions
|
||||||
|
|
||||||
import org.session.libsignal.service.loki.database.LokiThreadDatabaseProtocol
|
import org.session.libsignal.service.loki.database.LokiThreadDatabaseProtocol
|
||||||
import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol
|
import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol
|
Loading…
Reference in New Issue
Block a user