mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-28 10:10:48 +00:00
Make things compile
This commit is contained in:
parent
5120565a03
commit
21554441f3
@ -102,12 +102,11 @@ import org.whispersystems.signalservice.loki.api.Poller;
|
|||||||
import org.whispersystems.signalservice.loki.api.PushNotificationAcknowledgement;
|
import org.whispersystems.signalservice.loki.api.PushNotificationAcknowledgement;
|
||||||
import org.whispersystems.signalservice.loki.api.SnodeAPI;
|
import org.whispersystems.signalservice.loki.api.SnodeAPI;
|
||||||
import org.whispersystems.signalservice.loki.api.SwarmAPI;
|
import org.whispersystems.signalservice.loki.api.SwarmAPI;
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI;
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatAPI;
|
||||||
import org.whispersystems.signalservice.loki.api.shelved.p2p.LokiP2PAPI;
|
import org.whispersystems.signalservice.loki.api.shelved.p2p.LokiP2PAPI;
|
||||||
import org.whispersystems.signalservice.loki.api.shelved.p2p.LokiP2PAPIDelegate;
|
import org.whispersystems.signalservice.loki.api.shelved.p2p.LokiP2PAPIDelegate;
|
||||||
import org.whispersystems.signalservice.loki.database.LokiAPIDatabaseProtocol;
|
import org.whispersystems.signalservice.loki.database.LokiAPIDatabaseProtocol;
|
||||||
import org.whispersystems.signalservice.loki.protocol.friendrequests.FriendRequestProtocol;
|
|
||||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
|
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
|
||||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
|
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
|
||||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink;
|
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink;
|
||||||
@ -156,7 +155,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
public MessageNotifier messageNotifier = null;
|
public MessageNotifier messageNotifier = null;
|
||||||
public Poller lokiPoller = null;
|
public Poller lokiPoller = null;
|
||||||
public LokiPublicChatManager lokiPublicChatManager = null;
|
public LokiPublicChatManager lokiPublicChatManager = null;
|
||||||
private LokiPublicChatAPI lokiPublicChatAPI = null;
|
private PublicChatAPI publicChatAPI = null;
|
||||||
public Broadcaster broadcaster = null;
|
public Broadcaster broadcaster = null;
|
||||||
public SignalCommunicationModule communicationModule;
|
public SignalCommunicationModule communicationModule;
|
||||||
|
|
||||||
@ -189,7 +188,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
if (userPublicKey != null) {
|
if (userPublicKey != null) {
|
||||||
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||||
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||||
FriendRequestProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
|
||||||
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
||||||
SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||||
SyncMessagesProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
SyncMessagesProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||||
@ -201,7 +199,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
if (setUpStorageAPIIfNeeded()) {
|
if (setUpStorageAPIIfNeeded()) {
|
||||||
if (userPublicKey != null) {
|
if (userPublicKey != null) {
|
||||||
Set<DeviceLink> deviceLinks = DatabaseFactory.getLokiAPIDatabase(this).getDeviceLinks(userPublicKey);
|
Set<DeviceLink> deviceLinks = DatabaseFactory.getLokiAPIDatabase(this).getDeviceLinks(userPublicKey);
|
||||||
LokiFileServerAPI.shared.setDeviceLinks(deviceLinks);
|
FileServerAPI.shared.setDeviceLinks(deviceLinks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resubmitProfilePictureIfNeeded();
|
resubmitProfilePictureIfNeeded();
|
||||||
@ -284,15 +282,15 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Loki
|
// Loki
|
||||||
public @Nullable LokiPublicChatAPI getLokiPublicChatAPI() {
|
public @Nullable PublicChatAPI getPublicChatAPI() {
|
||||||
if (lokiPublicChatAPI != null || !IdentityKeyUtil.hasIdentityKey(this)) { return lokiPublicChatAPI; }
|
if (publicChatAPI != null || !IdentityKeyUtil.hasIdentityKey(this)) { return publicChatAPI; }
|
||||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||||
if (userPublicKey== null) { return lokiPublicChatAPI; }
|
if (userPublicKey== null) { return publicChatAPI; }
|
||||||
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
||||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||||
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
||||||
lokiPublicChatAPI = new LokiPublicChatAPI(userPublicKey, userPrivateKey, apiDB, userDB);
|
publicChatAPI = new PublicChatAPI(userPublicKey, userPrivateKey, apiDB, userDB);
|
||||||
return lokiPublicChatAPI;
|
return publicChatAPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeSecurityProvider() {
|
private void initializeSecurityProvider() {
|
||||||
@ -446,8 +444,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
super.attachBaseContext(DynamicLanguageContextWrapper.updateContext(base, TextSecurePreferences.getLanguage(base)));
|
super.attachBaseContext(DynamicLanguageContextWrapper.updateContext(base, TextSecurePreferences.getLanguage(base)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ProviderInitializationException extends RuntimeException {
|
private static class ProviderInitializationException extends RuntimeException { }
|
||||||
}
|
|
||||||
|
|
||||||
// region Loki
|
// region Loki
|
||||||
public boolean setUpStorageAPIIfNeeded() {
|
public boolean setUpStorageAPIIfNeeded() {
|
||||||
@ -456,7 +453,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
boolean isDebugMode = BuildConfig.DEBUG;
|
boolean isDebugMode = BuildConfig.DEBUG;
|
||||||
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
||||||
LokiAPIDatabaseProtocol apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
LokiAPIDatabaseProtocol apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||||
LokiFileServerAPI.Companion.configure(isDebugMode, userPublicKey, userPrivateKey, apiDB);
|
FileServerAPI.Companion.configure(userPublicKey, userPrivateKey, apiDB);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,7 +531,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
try {
|
try {
|
||||||
File profilePicture = AvatarHelper.getAvatarFile(this, Address.fromSerialized(userPublicKey));
|
File profilePicture = AvatarHelper.getAvatarFile(this, Address.fromSerialized(userPublicKey));
|
||||||
StreamDetails stream = new StreamDetails(new FileInputStream(profilePicture), "image/jpeg", profilePicture.length());
|
StreamDetails stream = new StreamDetails(new FileInputStream(profilePicture), "image/jpeg", profilePicture.length());
|
||||||
LokiFileServerAPI.shared.uploadProfilePicture(LokiFileServerAPI.shared.getServer(), profileKey, stream, () -> {
|
FileServerAPI.shared.uploadProfilePicture(FileServerAPI.shared.getServer(), profileKey, stream, () -> {
|
||||||
TextSecurePreferences.setLastProfilePictureUpload(this, new Date().getTime());
|
TextSecurePreferences.setLastProfilePictureUpload(this, new Date().getTime());
|
||||||
TextSecurePreferences.setProfileAvatarId(this, new SecureRandom().nextInt());
|
TextSecurePreferences.setProfileAvatarId(this, new SecureRandom().nextInt());
|
||||||
ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey);
|
ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey);
|
||||||
@ -548,9 +545,9 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
|
|
||||||
public void updateOpenGroupProfilePicturesIfNeeded() {
|
public void updateOpenGroupProfilePicturesIfNeeded() {
|
||||||
AsyncTask.execute(() -> {
|
AsyncTask.execute(() -> {
|
||||||
LokiPublicChatAPI publicChatAPI = null;
|
PublicChatAPI publicChatAPI = null;
|
||||||
try {
|
try {
|
||||||
publicChatAPI = getLokiPublicChatAPI();
|
publicChatAPI = getPublicChatAPI();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
@ -590,7 +587,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendSessionRequest(@NotNull String publicKey) {
|
public void sendSessionRequestIfNeeded(@NotNull String publicKey) {
|
||||||
// It's never necessary to establish a session with self
|
// It's never necessary to establish a session with self
|
||||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||||
if (publicKey.equals(userPublicKey)) { return; }
|
if (publicKey.equals(userPublicKey)) { return; }
|
||||||
|
@ -58,8 +58,8 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
|||||||
import org.whispersystems.signalservice.api.crypto.ProfileCipher;
|
import org.whispersystems.signalservice.api.crypto.ProfileCipher;
|
||||||
import org.whispersystems.signalservice.api.util.StreamDetails;
|
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||||
import org.whispersystems.signalservice.loki.api.LokiDotNetAPI;
|
import org.whispersystems.signalservice.loki.api.LokiDotNetAPI;
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI;
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatAPI;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -386,7 +386,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
|||||||
Context context = CreateProfileActivity.this;
|
Context context = CreateProfileActivity.this;
|
||||||
|
|
||||||
TextSecurePreferences.setProfileName(context, name);
|
TextSecurePreferences.setProfileName(context, name);
|
||||||
LokiPublicChatAPI publicChatAPI = ApplicationContext.getInstance(context).getLokiPublicChatAPI();
|
PublicChatAPI publicChatAPI = ApplicationContext.getInstance(context).getPublicChatAPI();
|
||||||
if (publicChatAPI != null) {
|
if (publicChatAPI != null) {
|
||||||
Set<String> servers = DatabaseFactory.getLokiThreadDatabase(context).getAllPublicChatServers();
|
Set<String> servers = DatabaseFactory.getLokiThreadDatabase(context).getAllPublicChatServers();
|
||||||
for (String server : servers) {
|
for (String server : servers) {
|
||||||
@ -409,7 +409,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
|||||||
// Loki - Upload the profile photo here
|
// Loki - Upload the profile photo here
|
||||||
if (avatar != null) {
|
if (avatar != null) {
|
||||||
Log.d("Loki", "Start uploading profile photo");
|
Log.d("Loki", "Start uploading profile photo");
|
||||||
LokiFileServerAPI storageAPI = LokiFileServerAPI.shared;
|
FileServerAPI storageAPI = FileServerAPI.shared;
|
||||||
LokiDotNetAPI.UploadResult result = storageAPI.uploadProfilePicture(storageAPI.getServer(), profileKey, avatar, () -> {
|
LokiDotNetAPI.UploadResult result = storageAPI.uploadProfilePicture(storageAPI.getServer(), profileKey, avatar, () -> {
|
||||||
TextSecurePreferences.setLastProfilePictureUpload(CreateProfileActivity.this, new Date().getTime());
|
TextSecurePreferences.setLastProfilePictureUpload(CreateProfileActivity.this, new Date().getTime());
|
||||||
return Unit.INSTANCE;
|
return Unit.INSTANCE;
|
||||||
|
@ -31,7 +31,7 @@ import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
|||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -197,7 +197,7 @@ public class QuoteView extends FrameLayout implements RecipientModifiedListener
|
|||||||
|
|
||||||
long threadID = DatabaseFactory.getThreadDatabase(getContext()).getThreadIdFor(conversationRecipient);
|
long threadID = DatabaseFactory.getThreadDatabase(getContext()).getThreadIdFor(conversationRecipient);
|
||||||
String senderHexEncodedPublicKey = author.getAddress().serialize();
|
String senderHexEncodedPublicKey = author.getAddress().serialize();
|
||||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadID);
|
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadID);
|
||||||
if (senderHexEncodedPublicKey.equalsIgnoreCase(TextSecurePreferences.getLocalNumber(getContext()))) {
|
if (senderHexEncodedPublicKey.equalsIgnoreCase(TextSecurePreferences.getLocalNumber(getContext()))) {
|
||||||
quoteeDisplayName = TextSecurePreferences.getProfileName(getContext());
|
quoteeDisplayName = TextSecurePreferences.getProfileName(getContext());
|
||||||
} else if (publicChat != null) {
|
} else if (publicChat != null) {
|
||||||
|
@ -187,7 +187,6 @@ import org.thoughtcrime.securesms.mms.StickerSlide;
|
|||||||
import org.thoughtcrime.securesms.mms.TextSlide;
|
import org.thoughtcrime.securesms.mms.TextSlide;
|
||||||
import org.thoughtcrime.securesms.mms.VideoSlide;
|
import org.thoughtcrime.securesms.mms.VideoSlide;
|
||||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.thoughtcrime.securesms.profiles.GroupShareProfileView;
|
import org.thoughtcrime.securesms.profiles.GroupShareProfileView;
|
||||||
@ -227,7 +226,7 @@ import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
|
|||||||
import org.thoughtcrime.securesms.util.views.Stub;
|
import org.thoughtcrime.securesms.util.views.Stub;
|
||||||
import org.whispersystems.libsignal.InvalidMessageException;
|
import org.whispersystems.libsignal.InvalidMessageException;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat;
|
||||||
import org.whispersystems.signalservice.loki.protocol.mentions.Mention;
|
import org.whispersystems.signalservice.loki.protocol.mentions.Mention;
|
||||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
|
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
|
||||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
|
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
|
||||||
@ -465,9 +464,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
MentionManagerUtilities.INSTANCE.populateUserPublicKeyCacheIfNeeded(threadId, this);
|
MentionManagerUtilities.INSTANCE.populateUserPublicKeyCacheIfNeeded(threadId, this);
|
||||||
|
|
||||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||||
if (publicChat != null) {
|
if (publicChat != null) {
|
||||||
ApplicationContext.getInstance(this).getLokiPublicChatAPI().getChannelInfo(publicChat.getChannel(), publicChat.getServer()).success( displayName -> {
|
ApplicationContext.getInstance(this).getPublicChatAPI().getChannelInfo(publicChat.getChannel(), publicChat.getServer()).success(displayName -> {
|
||||||
updateSubtitleTextView();
|
updateSubtitleTextView();
|
||||||
return Unit.INSTANCE;
|
return Unit.INSTANCE;
|
||||||
});
|
});
|
||||||
@ -2172,7 +2171,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
try {
|
try {
|
||||||
int startIndex = result.indexOf("@" + mention.getDisplayName());
|
int startIndex = result.indexOf("@" + mention.getDisplayName());
|
||||||
int endIndex = startIndex + mention.getDisplayName().length() + 1; // + 1 to include the @
|
int endIndex = startIndex + mention.getDisplayName().length() + 1; // + 1 to include the @
|
||||||
result = result.substring(0, startIndex) + "@" + mention.getHexEncodedPublicKey() + result.substring(endIndex);
|
result = result.substring(0, startIndex) + "@" + mention.getPublicKey() + result.substring(endIndex);
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
Log.d("Loki", "Couldn't process mention due to error: " + exception.toString() + ".");
|
Log.d("Loki", "Couldn't process mention due to error: " + exception.toString() + ".");
|
||||||
}
|
}
|
||||||
@ -3107,7 +3106,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
muteIndicatorImageView.setVisibility(View.VISIBLE);
|
muteIndicatorImageView.setVisibility(View.VISIBLE);
|
||||||
subtitleTextView.setText("Muted until " + DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault()));
|
subtitleTextView.setText("Muted until " + DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault()));
|
||||||
} else if (recipient.isGroupRecipient() && recipient.getName() != null && !recipient.getName().equals("Session Updates") && !recipient.getName().equals("Loki News")) {
|
} else if (recipient.isGroupRecipient() && recipient.getName() != null && !recipient.getName().equals("Session Updates") && !recipient.getName().equals("Loki News")) {
|
||||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||||
if (publicChat != null) {
|
if (publicChat != null) {
|
||||||
Integer userCount = DatabaseFactory.getLokiAPIDatabase(this).getUserCount(publicChat.getChannel(), publicChat.getServer());
|
Integer userCount = DatabaseFactory.getLokiAPIDatabase(this).getUserCount(publicChat.getChannel(), publicChat.getServer());
|
||||||
if (userCount == null) { userCount = 0; }
|
if (userCount == null) { userCount = 0; }
|
||||||
|
@ -101,8 +101,8 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
|||||||
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
|
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
|
||||||
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
|
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat;
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatAPI;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -399,7 +399,7 @@ public class ConversationFragment extends Fragment
|
|||||||
boolean isGroupChat = recipient.isGroupRecipient();
|
boolean isGroupChat = recipient.isGroupRecipient();
|
||||||
|
|
||||||
if (isGroupChat) {
|
if (isGroupChat) {
|
||||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||||
boolean isPublicChat = (publicChat != null);
|
boolean isPublicChat = (publicChat != null);
|
||||||
int selectedMessageCount = messageRecords.size();
|
int selectedMessageCount = messageRecords.size();
|
||||||
boolean areAllSentByUser = true;
|
boolean areAllSentByUser = true;
|
||||||
@ -409,7 +409,7 @@ public class ConversationFragment extends Fragment
|
|||||||
menu.findItem(R.id.menu_context_copy_public_key).setVisible(isPublicChat && selectedMessageCount == 1 && !areAllSentByUser);
|
menu.findItem(R.id.menu_context_copy_public_key).setVisible(isPublicChat && selectedMessageCount == 1 && !areAllSentByUser);
|
||||||
menu.findItem(R.id.menu_context_reply).setVisible(selectedMessageCount == 1);
|
menu.findItem(R.id.menu_context_reply).setVisible(selectedMessageCount == 1);
|
||||||
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(getContext());
|
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(getContext());
|
||||||
boolean userCanModerate = isPublicChat && LokiPublicChatAPI.Companion.isUserModerator(userHexEncodedPublicKey, publicChat.getChannel(), publicChat.getServer());
|
boolean userCanModerate = isPublicChat && PublicChatAPI.Companion.isUserModerator(userHexEncodedPublicKey, publicChat.getChannel(), publicChat.getServer());
|
||||||
boolean isDeleteOptionVisible = !isPublicChat || (areAllSentByUser || userCanModerate);
|
boolean isDeleteOptionVisible = !isPublicChat || (areAllSentByUser || userCanModerate);
|
||||||
menu.findItem(R.id.menu_context_delete_message).setVisible(isDeleteOptionVisible);
|
menu.findItem(R.id.menu_context_delete_message).setVisible(isDeleteOptionVisible);
|
||||||
} else {
|
} else {
|
||||||
@ -502,7 +502,7 @@ public class ConversationFragment extends Fragment
|
|||||||
builder.setMessage(getActivity().getResources().getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messagesCount, messagesCount));
|
builder.setMessage(getActivity().getResources().getQuantityString(R.plurals.ConversationFragment_this_will_permanently_delete_all_n_selected_messages, messagesCount, messagesCount));
|
||||||
builder.setCancelable(true);
|
builder.setCancelable(true);
|
||||||
|
|
||||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||||
|
|
||||||
builder.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
|
builder.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -518,7 +518,7 @@ public class ConversationFragment extends Fragment
|
|||||||
ArrayList<Long> ignoredMessages = new ArrayList<>();
|
ArrayList<Long> ignoredMessages = new ArrayList<>();
|
||||||
ArrayList<Long> failedMessages = new ArrayList<>();
|
ArrayList<Long> failedMessages = new ArrayList<>();
|
||||||
boolean isSentByUser = true;
|
boolean isSentByUser = true;
|
||||||
LokiPublicChatAPI publicChatAPI = ApplicationContext.getInstance(getContext()).getLokiPublicChatAPI();
|
PublicChatAPI publicChatAPI = ApplicationContext.getInstance(getContext()).getPublicChatAPI();
|
||||||
for (MessageRecord messageRecord : messageRecords) {
|
for (MessageRecord messageRecord : messageRecords) {
|
||||||
isSentByUser = isSentByUser && messageRecord.isOutgoing();
|
isSentByUser = isSentByUser && messageRecord.isOutgoing();
|
||||||
Long serverID = DatabaseFactory.getLokiMessageDatabase(getContext()).getServerID(messageRecord.id);
|
Long serverID = DatabaseFactory.getLokiMessageDatabase(getContext()).getServerID(messageRecord.id);
|
||||||
|
@ -112,8 +112,8 @@ import org.thoughtcrime.securesms.util.Util;
|
|||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
import org.thoughtcrime.securesms.util.views.Stub;
|
import org.thoughtcrime.securesms.util.views.Stub;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat;
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatAPI;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -1001,9 +1001,9 @@ public class ConversationItem extends LinearLayout
|
|||||||
profilePictureView.setVisibility(VISIBLE);
|
profilePictureView.setVisibility(VISIBLE);
|
||||||
int visibility = View.GONE;
|
int visibility = View.GONE;
|
||||||
|
|
||||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(messageRecord.getThreadId());
|
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(messageRecord.getThreadId());
|
||||||
if (publicChat != null) {
|
if (publicChat != null) {
|
||||||
boolean isModerator = LokiPublicChatAPI.Companion.isUserModerator(current.getRecipient().getAddress().toString(), publicChat.getChannel(), publicChat.getServer());
|
boolean isModerator = PublicChatAPI.Companion.isUserModerator(current.getRecipient().getAddress().toString(), publicChat.getChannel(), publicChat.getServer());
|
||||||
visibility = isModerator ? View.VISIBLE : View.GONE;
|
visibility = isModerator ? View.VISIBLE : View.GONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
|||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@ -545,7 +545,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
try (Cursor lokiPublicChatCursor = db.rawQuery("SELECT public_chat FROM loki_public_chat_database", null)) {
|
try (Cursor lokiPublicChatCursor = db.rawQuery("SELECT public_chat FROM loki_public_chat_database", null)) {
|
||||||
while (lokiPublicChatCursor != null && lokiPublicChatCursor.moveToNext()) {
|
while (lokiPublicChatCursor != null && lokiPublicChatCursor.moveToNext()) {
|
||||||
String chatString = lokiPublicChatCursor.getString(0);
|
String chatString = lokiPublicChatCursor.getString(0);
|
||||||
LokiPublicChat publicChat = LokiPublicChat.fromJSON(chatString);
|
PublicChat publicChat = PublicChat.fromJSON(chatString);
|
||||||
if (publicChat != null) {
|
if (publicChat != null) {
|
||||||
byte[] groupId = publicChat.getId().getBytes();
|
byte[] groupId = publicChat.getId().getBytes();
|
||||||
String oldId = GroupUtil.getEncodedId(groupId, false);
|
String oldId = GroupUtil.getEncodedId(groupId, false);
|
||||||
|
@ -152,7 +152,6 @@ public class SignalCommunicationModule {
|
|||||||
Optional.fromNullable(IncomingMessageObserver.getUnidentifiedPipe()),
|
Optional.fromNullable(IncomingMessageObserver.getUnidentifiedPipe()),
|
||||||
Optional.of(new MessageSenderEventListener(context)),
|
Optional.of(new MessageSenderEventListener(context)),
|
||||||
TextSecurePreferences.getLocalNumber(context),
|
TextSecurePreferences.getLocalNumber(context),
|
||||||
TextSecurePreferences.getMasterHexEncodedPublicKey(context),
|
|
||||||
DatabaseFactory.getLokiAPIDatabase(context),
|
DatabaseFactory.getLokiAPIDatabase(context),
|
||||||
DatabaseFactory.getLokiThreadDatabase(context),
|
DatabaseFactory.getLokiThreadDatabase(context),
|
||||||
DatabaseFactory.getLokiMessageDatabase(context),
|
DatabaseFactory.getLokiMessageDatabase(context),
|
||||||
|
@ -27,7 +27,6 @@ import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
|||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -73,7 +73,6 @@ import org.thoughtcrime.securesms.loki.protocol.FriendRequestProtocol;
|
|||||||
import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation;
|
import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.PushEphemeralMessageSendJob;
|
import org.thoughtcrime.securesms.loki.protocol.PushEphemeralMessageSendJob;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.PushNullMessageSendJob;
|
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
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.SyncMessagesProtocol;
|
import org.thoughtcrime.securesms.loki.protocol.SyncMessagesProtocol;
|
||||||
@ -103,7 +102,7 @@ import org.thoughtcrime.securesms.util.Hex;
|
|||||||
import org.thoughtcrime.securesms.util.IdentityUtil;
|
import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.whispersystems.libsignal.loki.LokiSessionResetProtocol;
|
import org.whispersystems.libsignal.loki.SessionResetProtocol;
|
||||||
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||||
@ -128,7 +127,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOper
|
|||||||
import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
|
import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
|
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI;
|
||||||
import org.whispersystems.signalservice.loki.crypto.LokiServiceCipher;
|
import org.whispersystems.signalservice.loki.crypto.LokiServiceCipher;
|
||||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
|
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
|
||||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus;
|
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus;
|
||||||
@ -265,9 +264,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);
|
||||||
LokiSessionResetProtocol lokiSessionResetProtocol = new LokiSessionResetImplementation(context);
|
SessionResetProtocol sessionResetProtocol = new LokiSessionResetImplementation(context);
|
||||||
SignalServiceAddress localAddress = new SignalServiceAddress(TextSecurePreferences.getLocalNumber(context));
|
SignalServiceAddress localAddress = new SignalServiceAddress(TextSecurePreferences.getLocalNumber(context));
|
||||||
LokiServiceCipher cipher = new LokiServiceCipher(localAddress, axolotlStore, lokiSessionResetProtocol, UnidentifiedAccessUtil.getCertificateValidator());
|
LokiServiceCipher cipher = new LokiServiceCipher(localAddress, axolotlStore, sessionResetProtocol, UnidentifiedAccessUtil.getCertificateValidator());
|
||||||
|
|
||||||
SignalServiceContent content = cipher.decrypt(envelope);
|
SignalServiceContent content = cipher.decrypt(envelope);
|
||||||
|
|
||||||
@ -298,12 +297,9 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getPreviews().isPresent() || message.getSticker().isPresent();
|
boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getPreviews().isPresent() || message.getSticker().isPresent();
|
||||||
|
|
||||||
// Loki - Handle unlinking request if needed
|
// Loki - Handle unlinking request if needed
|
||||||
if (message.isUnlinkingRequest()) {
|
if (message.isDeviceUnlinkingRequest()) {
|
||||||
MultiDeviceProtocol.handleUnlinkingRequestIfNeeded(context, content);
|
MultiDeviceProtocol.handleUnlinkingRequestIfNeeded(context, content);
|
||||||
} else {
|
} else {
|
||||||
// Loki - Don't process session restoration requests any further
|
|
||||||
if (message.isSessionRestorationRequest()) { return; }
|
|
||||||
|
|
||||||
// Loki - Handle friend request acceptance if needed
|
// Loki - Handle friend request acceptance if needed
|
||||||
FriendRequestProtocol.handleFriendRequestAcceptanceIfNeeded(context, content.getSender(), content);
|
FriendRequestProtocol.handleFriendRequestAcceptanceIfNeeded(context, content.getSender(), content);
|
||||||
|
|
||||||
@ -371,11 +367,11 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
|
|
||||||
// Loki - This is needed for compatibility with refactored desktop clients
|
// Loki - This is needed for compatibility with refactored desktop clients
|
||||||
// ========
|
// ========
|
||||||
if (content.isFriendRequest()) {
|
// if (content.isFriendRequest()) {
|
||||||
ApplicationContext.getInstance(context).getJobManager().add(new PushNullMessageSendJob(content.getSender()));
|
// ApplicationContext.getInstance(context).getJobManager().add(new PushNullMessageSendJob(content.getSender()));
|
||||||
} else {
|
// } else {
|
||||||
Log.w(TAG, "Got unrecognized message...");
|
// Log.w(TAG, "Got unrecognized message...");
|
||||||
}
|
// }
|
||||||
Recipient recipient = recipient(context, content.getSender());
|
Recipient recipient = recipient(context, content.getSender());
|
||||||
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context);
|
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context);
|
||||||
@ -1432,7 +1428,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
// TODO: Burn this with fire when we can
|
// TODO: Burn this with fire when we can
|
||||||
PromiseUtilities.timeout(LokiFileServerAPI.shared.getDeviceLinks(publicKey, false), 6000).get();
|
PromiseUtilities.timeout(FileServerAPI.shared.getDeviceLinks(publicKey, false), 6000).get();
|
||||||
String masterPublicKey = org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol.shared.getMasterDevice(publicKey);
|
String masterPublicKey = org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol.shared.getMasterDevice(publicKey);
|
||||||
if (masterPublicKey == null) {
|
if (masterPublicKey == null) {
|
||||||
masterPublicKey = publicKey;
|
masterPublicKey = publicKey;
|
||||||
@ -1464,7 +1460,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
// TODO: Burn this with fire when we can
|
// TODO: Burn this with fire when we can
|
||||||
PromiseUtilities.timeout(LokiFileServerAPI.shared.getDeviceLinks(publicKey, false), 6000).get();
|
PromiseUtilities.timeout(FileServerAPI.shared.getDeviceLinks(publicKey, false), 6000).get();
|
||||||
String masterPublicKey = org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol.shared.getMasterDevice(publicKey);
|
String masterPublicKey = org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol.shared.getMasterDevice(publicKey);
|
||||||
if (masterPublicKey == null) {
|
if (masterPublicKey == null) {
|
||||||
masterPublicKey = publicKey;
|
masterPublicKey = publicKey;
|
||||||
|
@ -291,7 +291,6 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
|||||||
.withPreviews(previews)
|
.withPreviews(previews)
|
||||||
.asExpirationUpdate(message.isExpirationUpdate())
|
.asExpirationUpdate(message.isExpirationUpdate())
|
||||||
.withPreKeyBundle(preKeyBundle)
|
.withPreKeyBundle(preKeyBundle)
|
||||||
.asFriendRequest(isLokiPreKeyBundleMessage)
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (SessionMetaProtocol.shared.isNoteToSelf(address.getNumber())) {
|
if (SessionMetaProtocol.shared.isNoteToSelf(address.getNumber())) {
|
||||||
|
@ -36,7 +36,7 @@ public abstract class PushReceivedJob extends BaseJob {
|
|||||||
|
|
||||||
if (envelope.isReceipt()) {
|
if (envelope.isReceipt()) {
|
||||||
handleReceipt(envelope);
|
handleReceipt(envelope);
|
||||||
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage() || envelope.isUnidentifiedSender() || envelope.isFriendRequest()) {
|
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage() || envelope.isUnidentifiedSender()) {
|
||||||
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());
|
||||||
|
@ -16,7 +16,6 @@ import org.thoughtcrime.securesms.dependencies.InjectableType;
|
|||||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||||
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
||||||
@ -229,7 +228,6 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
|||||||
.withExpiration((int)(message.getExpiresIn() / 1000))
|
.withExpiration((int)(message.getExpiresIn() / 1000))
|
||||||
.withProfileKey(profileKey.orNull())
|
.withProfileKey(profileKey.orNull())
|
||||||
.asEndSessionMessage(message.isEndSession())
|
.asEndSessionMessage(message.isEndSession())
|
||||||
.asFriendRequest(isLokiPreKeyBundleMessage)
|
|
||||||
.withPreKeyBundle(preKeyBundle)
|
.withPreKeyBundle(preKeyBundle)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -40,10 +40,8 @@ import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetViewDelegat
|
|||||||
import org.thoughtcrime.securesms.loki.views.SeedReminderViewDelegate
|
import org.thoughtcrime.securesms.loki.views.SeedReminderViewDelegate
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import org.thoughtcrime.securesms.mms.GlideApp
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||||
import org.whispersystems.signalservice.loki.protocol.friendrequests.FriendRequestProtocol
|
|
||||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
|
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
|
||||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
||||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||||
@ -160,7 +158,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
|||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||||
val sessionResetImpl = LokiSessionResetImplementation(this)
|
val sessionResetImpl = LokiSessionResetImplementation(this)
|
||||||
if (userPublicKey != null) {
|
if (userPublicKey != null) {
|
||||||
FriendRequestProtocol.configureIfNeeded(apiDB, userPublicKey)
|
|
||||||
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
||||||
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||||
SyncMessagesProtocol.configureIfNeeded(apiDB, userPublicKey)
|
SyncMessagesProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||||
@ -175,7 +172,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
|||||||
}.map {
|
}.map {
|
||||||
it.recipient.address.toPhoneString()
|
it.recipient.address.toPhoneString()
|
||||||
}.toSet()
|
}.toSet()
|
||||||
LokiFileServerAPI.shared.getDeviceLinks(publicKeys)
|
FileServerAPI.shared.getDeviceLinks(publicKeys)
|
||||||
// TODO: Temporary hack to unbork existing clients
|
// TODO: Temporary hack to unbork existing clients
|
||||||
val allContacts = DatabaseFactory.getRecipientDatabase(this).allAddresses.map {
|
val allContacts = DatabaseFactory.getRecipientDatabase(this).allAddresses.map {
|
||||||
MultiDeviceProtocol.shared.getMasterDevice(it.serialize()) ?: it.serialize()
|
MultiDeviceProtocol.shared.getMasterDevice(it.serialize()) ?: it.serialize()
|
||||||
@ -311,7 +308,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
|||||||
val apiDatabase = DatabaseFactory.getLokiAPIDatabase(activity)
|
val apiDatabase = DatabaseFactory.getLokiAPIDatabase(activity)
|
||||||
apiDatabase.removeLastMessageServerID(publicChat.channel, publicChat.server)
|
apiDatabase.removeLastMessageServerID(publicChat.channel, publicChat.server)
|
||||||
apiDatabase.removeLastDeletionServerID(publicChat.channel, publicChat.server)
|
apiDatabase.removeLastDeletionServerID(publicChat.channel, publicChat.server)
|
||||||
ApplicationContext.getInstance(activity).lokiPublicChatAPI!!.leave(publicChat.channel, publicChat.server)
|
ApplicationContext.getInstance(activity).publicChatAPI!!.leave(publicChat.channel, publicChat.server)
|
||||||
}
|
}
|
||||||
threadDatabase.deleteConversation(threadID)
|
threadDatabase.deleteConversation(threadID)
|
||||||
ApplicationContext.getInstance(activity).messageNotifier.updateNotification(activity)
|
ApplicationContext.getInstance(activity).messageNotifier.updateNotification(activity)
|
||||||
|
@ -27,7 +27,6 @@ import org.whispersystems.curve25519.Curve25519
|
|||||||
import org.whispersystems.libsignal.ecc.Curve
|
import org.whispersystems.libsignal.ecc.Curve
|
||||||
import org.whispersystems.libsignal.ecc.ECKeyPair
|
import org.whispersystems.libsignal.ecc.ECKeyPair
|
||||||
import org.whispersystems.libsignal.util.KeyHelper
|
import org.whispersystems.libsignal.util.KeyHelper
|
||||||
import org.whispersystems.signalservice.loki.protocol.friendrequests.FriendRequestProtocol
|
|
||||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
|
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
|
||||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
||||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
||||||
@ -111,7 +110,6 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
|||||||
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||||
val sessionResetImpl = LokiSessionResetImplementation(this)
|
val sessionResetImpl = LokiSessionResetImplementation(this)
|
||||||
FriendRequestProtocol.configureIfNeeded(apiDB, userPublicKey)
|
|
||||||
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
||||||
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||||
org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol.configureIfNeeded(apiDB)
|
org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol.configureIfNeeded(apiDB)
|
||||||
@ -124,13 +122,13 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
|||||||
linkDeviceDialog.show(supportFragmentManager, "Link Device Dialog")
|
linkDeviceDialog.show(supportFragmentManager, "Link Device Dialog")
|
||||||
AsyncTask.execute {
|
AsyncTask.execute {
|
||||||
retryIfNeeded(8) {
|
retryIfNeeded(8) {
|
||||||
MultiDeviceProtocol.sendDeviceLinkMessage(this@LandingActivity, deviceLink.masterHexEncodedPublicKey, deviceLink)
|
MultiDeviceProtocol.sendDeviceLinkMessage(this@LandingActivity, deviceLink.masterPublicKey, deviceLink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
||||||
TextSecurePreferences.setMasterHexEncodedPublicKey(this, deviceLink.masterHexEncodedPublicKey)
|
TextSecurePreferences.setMasterHexEncodedPublicKey(this, deviceLink.masterPublicKey)
|
||||||
val intent = Intent(this, HomeActivity::class.java)
|
val intent = Intent(this, HomeActivity::class.java)
|
||||||
show(intent)
|
show(intent)
|
||||||
finish()
|
finish()
|
||||||
|
@ -26,7 +26,7 @@ import org.thoughtcrime.securesms.loki.utilities.recipient
|
|||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.concurrent.schedule
|
import kotlin.concurrent.schedule
|
||||||
|
|
||||||
@ -126,30 +126,30 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager
|
|||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||||
val apiDB = DatabaseFactory.getLokiAPIDatabase(this)
|
val apiDB = DatabaseFactory.getLokiAPIDatabase(this)
|
||||||
val deviceLinks = apiDB.getDeviceLinks(userPublicKey)
|
val deviceLinks = apiDB.getDeviceLinks(userPublicKey)
|
||||||
val deviceLink = deviceLinks.find { it.masterHexEncodedPublicKey == userPublicKey && it.slaveHexEncodedPublicKey == slaveDevicePublicKey }
|
val deviceLink = deviceLinks.find { it.masterPublicKey == userPublicKey && it.slavePublicKey == slaveDevicePublicKey }
|
||||||
if (deviceLink == null) {
|
if (deviceLink == null) {
|
||||||
return Toast.makeText(this, R.string.activity_linked_devices_unlinking_failed_message, Toast.LENGTH_LONG).show()
|
return Toast.makeText(this, R.string.activity_linked_devices_unlinking_failed_message, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
LokiFileServerAPI.shared.setDeviceLinks(setOf()).successUi {
|
FileServerAPI.shared.setDeviceLinks(setOf()).successUi {
|
||||||
DatabaseFactory.getLokiAPIDatabase(this).clearDeviceLinks(userPublicKey)
|
DatabaseFactory.getLokiAPIDatabase(this).clearDeviceLinks(userPublicKey)
|
||||||
deviceLinks.forEach { deviceLink ->
|
deviceLinks.forEach { deviceLink ->
|
||||||
// We don't use PushEphemeralMessageJob because want these messages to send before the pre key and
|
// We don't use PushEphemeralMessageJob because want these messages to send before the pre key and
|
||||||
// session associated with the slave device have been deleted
|
// session associated with the slave device have been deleted
|
||||||
val unlinkingRequest = SignalServiceDataMessage.newBuilder()
|
val unlinkingRequest = SignalServiceDataMessage.newBuilder()
|
||||||
.withTimestamp(System.currentTimeMillis())
|
.withTimestamp(System.currentTimeMillis())
|
||||||
.asUnlinkingRequest(true)
|
.asDeviceUnlinkingRequest(true)
|
||||||
val messageSender = ApplicationContext.getInstance(this@LinkedDevicesActivity).communicationModule.provideSignalMessageSender()
|
val messageSender = ApplicationContext.getInstance(this@LinkedDevicesActivity).communicationModule.provideSignalMessageSender()
|
||||||
val address = SignalServiceAddress(deviceLink.slaveHexEncodedPublicKey)
|
val address = SignalServiceAddress(deviceLink.slavePublicKey)
|
||||||
try {
|
try {
|
||||||
val udAccess = UnidentifiedAccessUtil.getAccessFor(this@LinkedDevicesActivity, recipient(this@LinkedDevicesActivity, deviceLink.slaveHexEncodedPublicKey))
|
val udAccess = UnidentifiedAccessUtil.getAccessFor(this@LinkedDevicesActivity, recipient(this@LinkedDevicesActivity, deviceLink.slavePublicKey))
|
||||||
messageSender.sendMessage(0, address, udAccess, unlinkingRequest.build()) // The message ID doesn't matter
|
messageSender.sendMessage(0, address, udAccess, unlinkingRequest.build()) // The message ID doesn't matter
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Loki", "Failed to send unlinking request due to error: $e.")
|
Log.d("Loki", "Failed to send unlinking request due to error: $e.")
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey)
|
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slavePublicKey)
|
||||||
val sessionStore = TextSecureSessionStore(this@LinkedDevicesActivity)
|
val sessionStore = TextSecureSessionStore(this@LinkedDevicesActivity)
|
||||||
sessionStore.deleteAllSessions(deviceLink.slaveHexEncodedPublicKey)
|
sessionStore.deleteAllSessions(deviceLink.slavePublicKey)
|
||||||
}
|
}
|
||||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||||
Toast.makeText(this, R.string.activity_linked_devices_unlinking_successful_message, Toast.LENGTH_LONG).show()
|
Toast.makeText(this, R.string.activity_linked_devices_unlinking_successful_message, Toast.LENGTH_LONG).show()
|
||||||
|
@ -42,7 +42,7 @@ import org.thoughtcrime.securesms.util.BitmapUtil
|
|||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.signalservice.api.crypto.ProfileCipher
|
import org.whispersystems.signalservice.api.crypto.ProfileCipher
|
||||||
import org.whispersystems.signalservice.api.util.StreamDetails
|
import org.whispersystems.signalservice.api.util.StreamDetails
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
@ -151,7 +151,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
val promises = mutableListOf<Promise<*, Exception>>()
|
val promises = mutableListOf<Promise<*, Exception>>()
|
||||||
val displayName = displayNameToBeUploaded
|
val displayName = displayNameToBeUploaded
|
||||||
if (displayName != null) {
|
if (displayName != null) {
|
||||||
val publicChatAPI = ApplicationContext.getInstance(this).lokiPublicChatAPI
|
val publicChatAPI = ApplicationContext.getInstance(this).publicChatAPI
|
||||||
if (publicChatAPI != null) {
|
if (publicChatAPI != null) {
|
||||||
val servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers()
|
val servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers()
|
||||||
promises.addAll(servers.map { publicChatAPI.setDisplayName(displayName, it) })
|
promises.addAll(servers.map { publicChatAPI.setDisplayName(displayName, it) })
|
||||||
@ -162,7 +162,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
val encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this)
|
val encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this)
|
||||||
val profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(encodedProfileKey)
|
val profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(encodedProfileKey)
|
||||||
if (isUpdatingProfilePicture && profilePicture != null) {
|
if (isUpdatingProfilePicture && profilePicture != null) {
|
||||||
val storageAPI = LokiFileServerAPI.shared
|
val storageAPI = FileServerAPI.shared
|
||||||
val deferred = deferred<Unit, Exception>()
|
val deferred = deferred<Unit, Exception>()
|
||||||
AsyncTask.execute {
|
AsyncTask.execute {
|
||||||
val stream = StreamDetails(ByteArrayInputStream(profilePicture), "image/jpeg", profilePicture.size.toLong())
|
val stream = StreamDetails(ByteArrayInputStream(profilePicture), "image/jpeg", profilePicture.size.toLong())
|
||||||
|
@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit
|
|||||||
class BackgroundPollWorker : PersistentAlarmManagerListener() {
|
class BackgroundPollWorker : PersistentAlarmManagerListener() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val pollInterval = TimeUnit.MINUTES.toMillis(15)
|
private val pollInterval = TimeUnit.MINUTES.toMillis(30)
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun schedule(context: Context) {
|
fun schedule(context: Context) {
|
||||||
|
@ -12,10 +12,10 @@ import org.thoughtcrime.securesms.database.DatabaseFactory
|
|||||||
import org.thoughtcrime.securesms.groups.GroupManager
|
import org.thoughtcrime.securesms.groups.GroupManager
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.thoughtcrime.securesms.util.Util
|
import org.thoughtcrime.securesms.util.Util
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||||
|
|
||||||
class LokiPublicChatManager(private val context: Context) {
|
class LokiPublicChatManager(private val context: Context) {
|
||||||
private var chats = mutableMapOf<Long, LokiPublicChat>()
|
private var chats = mutableMapOf<Long, PublicChat>()
|
||||||
private val pollers = mutableMapOf<Long, LokiPublicChatPoller>()
|
private val pollers = mutableMapOf<Long, LokiPublicChatPoller>()
|
||||||
private val observers = mutableMapOf<Long, ContentObserver>()
|
private val observers = mutableMapOf<Long, ContentObserver>()
|
||||||
private var isPolling = false
|
private var isPolling = false
|
||||||
@ -55,8 +55,8 @@ class LokiPublicChatManager(private val context: Context) {
|
|||||||
isPolling = false
|
isPolling = false
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun addChat(server: String, channel: Long): Promise<LokiPublicChat, Exception> {
|
public fun addChat(server: String, channel: Long): Promise<PublicChat, Exception> {
|
||||||
val groupChatAPI = ApplicationContext.getInstance(context).lokiPublicChatAPI ?: return Promise.ofFail(IllegalStateException("LokiPublicChatAPI is not set!"))
|
val groupChatAPI = ApplicationContext.getInstance(context).publicChatAPI ?: return Promise.ofFail(IllegalStateException("LokiPublicChatAPI is not set!"))
|
||||||
return groupChatAPI.getAuthToken(server).bind {
|
return groupChatAPI.getAuthToken(server).bind {
|
||||||
groupChatAPI.getChannelInfo(channel, server)
|
groupChatAPI.getChannelInfo(channel, server)
|
||||||
}.map {
|
}.map {
|
||||||
@ -64,8 +64,8 @@ class LokiPublicChatManager(private val context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun addChat(server: String, channel: Long, name: String): LokiPublicChat {
|
public fun addChat(server: String, channel: Long, name: String): PublicChat {
|
||||||
val chat = LokiPublicChat(channel, server, name, true)
|
val chat = PublicChat(channel, server, name, true)
|
||||||
var threadID = GroupManager.getOpenGroupThreadID(chat.id, context)
|
var threadID = GroupManager.getOpenGroupThreadID(chat.id, context)
|
||||||
// Create the group if we don't have one
|
// Create the group if we don't have one
|
||||||
if (threadID < 0) {
|
if (threadID < 0) {
|
||||||
@ -76,7 +76,7 @@ class LokiPublicChatManager(private val context: Context) {
|
|||||||
// Set our name on the server
|
// Set our name on the server
|
||||||
val displayName = TextSecurePreferences.getProfileName(context)
|
val displayName = TextSecurePreferences.getProfileName(context)
|
||||||
if (!TextUtils.isEmpty(displayName)) {
|
if (!TextUtils.isEmpty(displayName)) {
|
||||||
ApplicationContext.getInstance(context).lokiPublicChatAPI?.setDisplayName(displayName, server)
|
ApplicationContext.getInstance(context).publicChatAPI?.setDisplayName(displayName, server)
|
||||||
}
|
}
|
||||||
// Start polling
|
// Start polling
|
||||||
Util.runOnMain{ startPollersIfNeeded() }
|
Util.runOnMain{ startPollersIfNeeded() }
|
||||||
|
@ -22,16 +22,16 @@ import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
|||||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup
|
import org.whispersystems.signalservice.api.messages.SignalServiceGroup
|
||||||
import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage
|
import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatAPI
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatMessage
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatMessage
|
||||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class LokiPublicChatPoller(private val context: Context, private val group: LokiPublicChat) {
|
class LokiPublicChatPoller(private val context: Context, private val group: PublicChat) {
|
||||||
private val handler = Handler()
|
private val handler = Handler()
|
||||||
private var hasStarted = false
|
private var hasStarted = false
|
||||||
public var isCaughtUp = false
|
public var isCaughtUp = false
|
||||||
@ -40,12 +40,12 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
|||||||
private val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
private val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||||
private var displayNameUpdatees = setOf<String>()
|
private var displayNameUpdatees = setOf<String>()
|
||||||
|
|
||||||
private val api: LokiPublicChatAPI
|
private val api: PublicChatAPI
|
||||||
get() = {
|
get() = {
|
||||||
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
||||||
val lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(context)
|
val lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(context)
|
||||||
val lokiUserDatabase = DatabaseFactory.getLokiUserDatabase(context)
|
val lokiUserDatabase = DatabaseFactory.getLokiUserDatabase(context)
|
||||||
LokiPublicChatAPI(userHexEncodedPublicKey, userPrivateKey, lokiAPIDatabase, lokiUserDatabase)
|
PublicChatAPI(userHexEncodedPublicKey, userPrivateKey, lokiAPIDatabase, lokiUserDatabase)
|
||||||
}()
|
}()
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
@ -112,16 +112,16 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Polling
|
// region Polling
|
||||||
private fun getDataMessage(message: LokiPublicChatMessage): SignalServiceDataMessage {
|
private fun getDataMessage(message: PublicChatMessage): SignalServiceDataMessage {
|
||||||
val id = group.id.toByteArray()
|
val id = group.id.toByteArray()
|
||||||
val serviceGroup = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.PUBLIC_CHAT, null, null, null, null)
|
val serviceGroup = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.PUBLIC_CHAT, null, null, null, null)
|
||||||
val quote = if (message.quote != null) {
|
val quote = if (message.quote != null) {
|
||||||
SignalServiceDataMessage.Quote(message.quote!!.quotedMessageTimestamp, SignalServiceAddress(message.quote!!.quoteeHexEncodedPublicKey), message.quote!!.quotedMessageBody, listOf())
|
SignalServiceDataMessage.Quote(message.quote!!.quotedMessageTimestamp, SignalServiceAddress(message.quote!!.quoteePublicKey), message.quote!!.quotedMessageBody, listOf())
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
val attachments = message.attachments.mapNotNull { attachment ->
|
val attachments = message.attachments.mapNotNull { attachment ->
|
||||||
if (attachment.kind != LokiPublicChatMessage.Attachment.Kind.Attachment) { return@mapNotNull null }
|
if (attachment.kind != PublicChatMessage.Attachment.Kind.Attachment) { return@mapNotNull null }
|
||||||
SignalServiceAttachmentPointer(
|
SignalServiceAttachmentPointer(
|
||||||
attachment.serverID,
|
attachment.serverID,
|
||||||
attachment.contentType,
|
attachment.contentType,
|
||||||
@ -135,7 +135,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
|||||||
Optional.fromNullable(attachment.caption),
|
Optional.fromNullable(attachment.caption),
|
||||||
attachment.url)
|
attachment.url)
|
||||||
}
|
}
|
||||||
val linkPreview = message.attachments.firstOrNull { it.kind == LokiPublicChatMessage.Attachment.Kind.LinkPreview }
|
val linkPreview = message.attachments.firstOrNull { it.kind == PublicChatMessage.Attachment.Kind.LinkPreview }
|
||||||
val signalLinkPreviews = mutableListOf<SignalServiceDataMessage.Preview>()
|
val signalLinkPreviews = mutableListOf<SignalServiceDataMessage.Preview>()
|
||||||
if (linkPreview != null) {
|
if (linkPreview != null) {
|
||||||
val attachment = SignalServiceAttachmentPointer(
|
val attachment = SignalServiceAttachmentPointer(
|
||||||
@ -157,16 +157,16 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun pollForNewMessages() {
|
fun pollForNewMessages() {
|
||||||
fun processIncomingMessage(message: LokiPublicChatMessage) {
|
fun processIncomingMessage(message: PublicChatMessage) {
|
||||||
// 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 masterHexEncodedPublicKey = MultiDeviceProtocol.shared.getMasterDevice(message.hexEncodedPublicKey)
|
val masterHexEncodedPublicKey = MultiDeviceProtocol.shared.getMasterDevice(message.publicKey)
|
||||||
if (masterHexEncodedPublicKey == null) {
|
if (masterHexEncodedPublicKey == null) {
|
||||||
val senderDisplayName = "${message.displayName} (...${message.hexEncodedPublicKey.takeLast(8)})"
|
val senderDisplayName = "${message.displayName} (...${message.publicKey.takeLast(8)})"
|
||||||
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.hexEncodedPublicKey, senderDisplayName)
|
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.publicKey, senderDisplayName)
|
||||||
}
|
}
|
||||||
val senderHexEncodedPublicKey = masterHexEncodedPublicKey ?: message.hexEncodedPublicKey
|
val senderHexEncodedPublicKey = masterHexEncodedPublicKey ?: message.publicKey
|
||||||
val serviceDataMessage = getDataMessage(message)
|
val serviceDataMessage = getDataMessage(message)
|
||||||
val serviceContent = SignalServiceContent(serviceDataMessage, senderHexEncodedPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.timestamp, false, false, false, false)
|
val serviceContent = SignalServiceContent(serviceDataMessage, senderHexEncodedPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.timestamp, false, false, false)
|
||||||
if (serviceDataMessage.quote.isPresent || (serviceDataMessage.attachments.isPresent && serviceDataMessage.attachments.get().size > 0) || serviceDataMessage.previews.isPresent) {
|
if (serviceDataMessage.quote.isPresent || (serviceDataMessage.attachments.isPresent && serviceDataMessage.attachments.get().size > 0) || serviceDataMessage.previews.isPresent) {
|
||||||
PushDecryptJob(context).handleMediaMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
|
PushDecryptJob(context).handleMediaMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
|
||||||
} else {
|
} else {
|
||||||
@ -191,7 +191,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun processOutgoingMessage(message: LokiPublicChatMessage) {
|
fun processOutgoingMessage(message: PublicChatMessage) {
|
||||||
val messageServerID = message.serverID ?: return
|
val messageServerID = message.serverID ?: return
|
||||||
val isDuplicate = DatabaseFactory.getLokiMessageDatabase(context).getMessageID(messageServerID) != null
|
val isDuplicate = DatabaseFactory.getLokiMessageDatabase(context).getMessageID(messageServerID) != null
|
||||||
if (isDuplicate) { return }
|
if (isDuplicate) { return }
|
||||||
@ -206,7 +206,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
|||||||
PushDecryptJob(context).handleSynchronizeSentTextMessage(transcript)
|
PushDecryptJob(context).handleSynchronizeSentTextMessage(transcript)
|
||||||
}
|
}
|
||||||
// If we got a message from our master device then make sure our mapping stays in sync
|
// 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.hexEncodedPublicKey), false)
|
val recipient = Recipient.from(context, Address.fromSerialized(message.publicKey), false)
|
||||||
if (recipient.isUserMasterDevice && message.profilePicture != null) {
|
if (recipient.isUserMasterDevice && message.profilePicture != null) {
|
||||||
val profileKey = message.profilePicture!!.profileKey
|
val profileKey = message.profilePicture!!.profileKey
|
||||||
val url = message.profilePicture!!.url
|
val url = message.profilePicture!!.url
|
||||||
@ -222,15 +222,15 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
|||||||
var uniqueDevices = setOf<String>()
|
var uniqueDevices = setOf<String>()
|
||||||
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
||||||
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
|
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
|
||||||
LokiFileServerAPI.configure(false, userHexEncodedPublicKey, userPrivateKey, apiDB)
|
FileServerAPI.configure(userHexEncodedPublicKey, userPrivateKey, apiDB)
|
||||||
// Kovenant propagates a context to chained promises, so LokiPublicChatAPI.sharedContext should be used for all of the below
|
// Kovenant propagates a context to chained promises, so LokiPublicChatAPI.sharedContext should be used for all of the below
|
||||||
api.getMessages(group.channel, group.server).bind(LokiPublicChatAPI.sharedContext) { messages ->
|
api.getMessages(group.channel, group.server).bind(PublicChatAPI.sharedContext) { messages ->
|
||||||
if (messages.isNotEmpty()) {
|
if (messages.isNotEmpty()) {
|
||||||
// We need to fetch the device mapping for any devices we don't have
|
// We need to fetch the device mapping for any devices we don't have
|
||||||
uniqueDevices = messages.map { it.hexEncodedPublicKey }.toSet()
|
uniqueDevices = messages.map { it.publicKey }.toSet()
|
||||||
val devicesToUpdate = uniqueDevices.filter { !userDevices.contains(it) && LokiFileServerAPI.shared.hasDeviceLinkCacheExpired(hexEncodedPublicKey = it) }
|
val devicesToUpdate = uniqueDevices.filter { !userDevices.contains(it) && FileServerAPI.shared.hasDeviceLinkCacheExpired(publicKey = it) }
|
||||||
if (devicesToUpdate.isNotEmpty()) {
|
if (devicesToUpdate.isNotEmpty()) {
|
||||||
return@bind LokiFileServerAPI.shared.getDeviceLinks(devicesToUpdate.toSet()).then { messages }
|
return@bind FileServerAPI.shared.getDeviceLinks(devicesToUpdate.toSet()).then { messages }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Promise.of(messages)
|
Promise.of(messages)
|
||||||
@ -244,7 +244,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
|||||||
}.successBackground { messages ->
|
}.successBackground { messages ->
|
||||||
// Process messages in the background
|
// Process messages in the background
|
||||||
messages.forEach { message ->
|
messages.forEach { message ->
|
||||||
if (userDevices.contains(message.hexEncodedPublicKey)) {
|
if (userDevices.contains(message.publicKey)) {
|
||||||
processOutgoingMessage(message)
|
processOutgoingMessage(message)
|
||||||
} else {
|
} else {
|
||||||
processIncomingMessage(message)
|
processIncomingMessage(message)
|
||||||
|
@ -29,9 +29,9 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
@JvmStatic val createOnionRequestPathCacheCommand = "CREATE TABLE $onionRequestPathCache ($indexPath TEXT PRIMARY KEY, $snode TEXT);"
|
@JvmStatic val createOnionRequestPathCacheCommand = "CREATE TABLE $onionRequestPathCache ($indexPath TEXT PRIMARY KEY, $snode TEXT);"
|
||||||
// Swarm cache
|
// Swarm cache
|
||||||
private val swarmCache = "loki_api_swarm_cache"
|
private val swarmCache = "loki_api_swarm_cache"
|
||||||
private val hexEncodedPublicKey = "hex_encoded_public_key"
|
private val swarmPublicKey = "hex_encoded_public_key"
|
||||||
private val swarm = "swarm"
|
private val swarm = "swarm"
|
||||||
@JvmStatic val createSwarmCacheCommand = "CREATE TABLE $swarmCache ($hexEncodedPublicKey TEXT PRIMARY KEY, $swarm TEXT);"
|
@JvmStatic val createSwarmCacheCommand = "CREATE TABLE $swarmCache ($swarmPublicKey TEXT PRIMARY KEY, $swarm TEXT);"
|
||||||
// Last message hash value cache
|
// Last message hash value cache
|
||||||
private val lastMessageHashValueCache = "loki_api_last_message_hash_value_cache"
|
private val lastMessageHashValueCache = "loki_api_last_message_hash_value_cache"
|
||||||
private val target = "target"
|
private val target = "target"
|
||||||
@ -59,12 +59,12 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
@JvmStatic val createLastDeletionServerIDCacheCommand = "CREATE TABLE $lastDeletionServerIDCache ($lastDeletionServerIDCacheIndex STRING PRIMARY KEY, $lastDeletionServerID INTEGER DEFAULT 0);"
|
@JvmStatic val createLastDeletionServerIDCacheCommand = "CREATE TABLE $lastDeletionServerIDCache ($lastDeletionServerIDCacheIndex STRING PRIMARY KEY, $lastDeletionServerID INTEGER DEFAULT 0);"
|
||||||
// Device link cache
|
// Device link cache
|
||||||
private val deviceLinkCache = "loki_pairing_authorisation_cache"
|
private val deviceLinkCache = "loki_pairing_authorisation_cache"
|
||||||
private val masterHexEncodedPublicKey = "primary_device"
|
private val masterPublicKey = "primary_device"
|
||||||
private val slaveHexEncodedPublicKey = "secondary_device"
|
private val slavePublicKey = "secondary_device"
|
||||||
private val requestSignature = "request_signature"
|
private val requestSignature = "request_signature"
|
||||||
private val authorizationSignature = "grant_signature"
|
private val authorizationSignature = "grant_signature"
|
||||||
@JvmStatic val createDeviceLinkCacheCommand = "CREATE TABLE $deviceLinkCache ($masterHexEncodedPublicKey TEXT, $slaveHexEncodedPublicKey TEXT, " +
|
@JvmStatic val createDeviceLinkCacheCommand = "CREATE TABLE $deviceLinkCache ($masterPublicKey TEXT, $slavePublicKey TEXT, " +
|
||||||
"$requestSignature TEXT NULLABLE DEFAULT NULL, $authorizationSignature TEXT NULLABLE DEFAULT NULL, PRIMARY KEY ($masterHexEncodedPublicKey, $slaveHexEncodedPublicKey));"
|
"$requestSignature TEXT NULLABLE DEFAULT NULL, $authorizationSignature TEXT NULLABLE DEFAULT NULL, PRIMARY KEY ($masterPublicKey, $slavePublicKey));"
|
||||||
// User count cache
|
// User count cache
|
||||||
private val userCountCache = "loki_user_count_cache"
|
private val userCountCache = "loki_user_count_cache"
|
||||||
private val publicChatID = "public_chat_id"
|
private val publicChatID = "public_chat_id"
|
||||||
@ -72,9 +72,9 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
@JvmStatic val createUserCountCacheCommand = "CREATE TABLE $userCountCache ($publicChatID STRING PRIMARY KEY, $userCount INTEGER DEFAULT 0);"
|
@JvmStatic val createUserCountCacheCommand = "CREATE TABLE $userCountCache ($publicChatID STRING PRIMARY KEY, $userCount INTEGER DEFAULT 0);"
|
||||||
// Session request timestamp cache
|
// Session request timestamp cache
|
||||||
private val sessionRequestTimestampCache = "session_request_timestamp_cache"
|
private val sessionRequestTimestampCache = "session_request_timestamp_cache"
|
||||||
private val publicKey = "public_key"
|
private val sessionRequestPublicKey = "public_key"
|
||||||
private val timestamp = "timestamp"
|
private val timestamp = "timestamp"
|
||||||
@JvmStatic val createSessionRequestTimestampCacheCommand = "CREATE TABLE $sessionRequestTimestampCache ($publicKey STRING PRIMARY KEY, $timestamp INTEGER DEFAULT 0);"
|
@JvmStatic val createSessionRequestTimestampCacheCommand = "CREATE TABLE $sessionRequestTimestampCache ($sessionRequestPublicKey STRING PRIMARY KEY, $timestamp INTEGER DEFAULT 0);"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSnodePool(): Set<Snode> {
|
override fun getSnodePool(): Set<Snode> {
|
||||||
@ -161,9 +161,9 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
set("1-1", path1[1]); set("1-2", path1[2])
|
set("1-1", path1[1]); set("1-2", path1[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSwarm(hexEncodedPublicKey: String): Set<Snode>? {
|
override fun getSwarm(publicKey: String): Set<Snode>? {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(swarmCache, "${Companion.hexEncodedPublicKey} = ?", wrap(hexEncodedPublicKey)) { cursor ->
|
return database.get(swarmCache, "${Companion.swarmPublicKey} = ?", wrap(publicKey)) { cursor ->
|
||||||
val swarmAsString = cursor.getString(cursor.getColumnIndexOrThrow(swarm))
|
val swarmAsString = cursor.getString(cursor.getColumnIndexOrThrow(swarm))
|
||||||
swarmAsString.split(", ").mapNotNull { targetAsString ->
|
swarmAsString.split(", ").mapNotNull { targetAsString ->
|
||||||
val components = targetAsString.split("-")
|
val components = targetAsString.split("-")
|
||||||
@ -176,7 +176,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
}?.toSet()
|
}?.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setSwarm(hexEncodedPublicKey: String, newValue: Set<Snode>) {
|
override fun setSwarm(publicKey: String, newValue: Set<Snode>) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val swarmAsString = newValue.joinToString(", ") { target ->
|
val swarmAsString = newValue.joinToString(", ") { target ->
|
||||||
var string = "${target.address}-${target.port}"
|
var string = "${target.address}-${target.port}"
|
||||||
@ -186,21 +186,21 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
}
|
}
|
||||||
string
|
string
|
||||||
}
|
}
|
||||||
val row = wrap(mapOf(Companion.hexEncodedPublicKey to hexEncodedPublicKey, swarm to swarmAsString))
|
val row = wrap(mapOf(Companion.swarmPublicKey to publicKey, swarm to swarmAsString))
|
||||||
database.insertOrUpdate(swarmCache, row, "${Companion.hexEncodedPublicKey} = ?", wrap(hexEncodedPublicKey))
|
database.insertOrUpdate(swarmCache, row, "${Companion.swarmPublicKey} = ?", wrap(publicKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLastMessageHashValue(target: Snode): String? {
|
override fun getLastMessageHashValue(snode: Snode): String? {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(lastMessageHashValueCache, "${Companion.target} = ?", wrap(target.address)) { cursor ->
|
return database.get(lastMessageHashValueCache, "${Companion.target} = ?", wrap(snode.address)) { cursor ->
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(lastMessageHashValue))
|
cursor.getString(cursor.getColumnIndexOrThrow(lastMessageHashValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setLastMessageHashValue(target: Snode, newValue: String) {
|
override fun setLastMessageHashValue(snode: Snode, newValue: String) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val row = wrap(mapOf(Companion.target to target.address, lastMessageHashValue to newValue))
|
val row = wrap(mapOf(Companion.target to snode.address, lastMessageHashValue to newValue))
|
||||||
database.insertOrUpdate(lastMessageHashValueCache, row, "${Companion.target} = ?", wrap(target.address))
|
database.insertOrUpdate(lastMessageHashValueCache, row, "${Companion.target} = ?", wrap(snode.address))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getReceivedMessageHashValues(): Set<String>? {
|
override fun getReceivedMessageHashValues(): Set<String>? {
|
||||||
@ -277,35 +277,35 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
database.delete(lastDeletionServerIDCache,"$lastDeletionServerIDCacheIndex = ?", wrap(index))
|
database.delete(lastDeletionServerIDCache,"$lastDeletionServerIDCacheIndex = ?", wrap(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDeviceLinks(hexEncodedPublicKey: String): Set<DeviceLink> {
|
override fun getDeviceLinks(publicKey: String): Set<DeviceLink> {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.getAll(deviceLinkCache, "$masterHexEncodedPublicKey = ? OR $slaveHexEncodedPublicKey = ?", arrayOf( hexEncodedPublicKey, hexEncodedPublicKey )) { cursor ->
|
return database.getAll(deviceLinkCache, "$masterPublicKey = ? OR $slavePublicKey = ?", arrayOf( publicKey, publicKey )) { cursor ->
|
||||||
val masterHexEncodedPublicKey = cursor.getString(masterHexEncodedPublicKey)
|
val masterHexEncodedPublicKey = cursor.getString(masterPublicKey)
|
||||||
val slaveHexEncodedPublicKey = cursor.getString(slaveHexEncodedPublicKey)
|
val slaveHexEncodedPublicKey = cursor.getString(slavePublicKey)
|
||||||
val requestSignature: ByteArray? = if (cursor.isNull(cursor.getColumnIndexOrThrow(requestSignature))) null else cursor.getBase64EncodedData(requestSignature)
|
val requestSignature: ByteArray? = if (cursor.isNull(cursor.getColumnIndexOrThrow(requestSignature))) null else cursor.getBase64EncodedData(requestSignature)
|
||||||
val authorizationSignature: ByteArray? = if (cursor.isNull(cursor.getColumnIndexOrThrow(authorizationSignature))) null else cursor.getBase64EncodedData(authorizationSignature)
|
val authorizationSignature: ByteArray? = if (cursor.isNull(cursor.getColumnIndexOrThrow(authorizationSignature))) null else cursor.getBase64EncodedData(authorizationSignature)
|
||||||
DeviceLink(masterHexEncodedPublicKey, slaveHexEncodedPublicKey, requestSignature, authorizationSignature)
|
DeviceLink(masterHexEncodedPublicKey, slaveHexEncodedPublicKey, requestSignature, authorizationSignature)
|
||||||
}.toSet()
|
}.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clearDeviceLinks(hexEncodedPublicKey: String) {
|
override fun clearDeviceLinks(publicKey: String) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
database.delete(deviceLinkCache, "$masterHexEncodedPublicKey = ? OR $slaveHexEncodedPublicKey = ?", arrayOf( hexEncodedPublicKey, hexEncodedPublicKey ))
|
database.delete(deviceLinkCache, "$masterPublicKey = ? OR $slavePublicKey = ?", arrayOf( publicKey, publicKey ))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addDeviceLink(deviceLink: DeviceLink) {
|
override fun addDeviceLink(deviceLink: DeviceLink) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val values = ContentValues()
|
val values = ContentValues()
|
||||||
values.put(masterHexEncodedPublicKey, deviceLink.masterHexEncodedPublicKey)
|
values.put(masterPublicKey, deviceLink.masterPublicKey)
|
||||||
values.put(slaveHexEncodedPublicKey, deviceLink.slaveHexEncodedPublicKey)
|
values.put(slavePublicKey, deviceLink.slavePublicKey)
|
||||||
if (deviceLink.requestSignature != null) { values.put(requestSignature, Base64.encodeBytes(deviceLink.requestSignature)) }
|
if (deviceLink.requestSignature != null) { values.put(requestSignature, Base64.encodeBytes(deviceLink.requestSignature)) }
|
||||||
if (deviceLink.authorizationSignature != null) { values.put(authorizationSignature, Base64.encodeBytes(deviceLink.authorizationSignature)) }
|
if (deviceLink.authorizationSignature != null) { values.put(authorizationSignature, Base64.encodeBytes(deviceLink.authorizationSignature)) }
|
||||||
database.insertOrUpdate(deviceLinkCache, values, "$masterHexEncodedPublicKey = ? AND $slaveHexEncodedPublicKey = ?", arrayOf( deviceLink.masterHexEncodedPublicKey, deviceLink.slaveHexEncodedPublicKey ))
|
database.insertOrUpdate(deviceLinkCache, values, "$masterPublicKey = ? AND $slavePublicKey = ?", arrayOf( deviceLink.masterPublicKey, deviceLink.slavePublicKey ))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removeDeviceLink(deviceLink: DeviceLink) {
|
override fun removeDeviceLink(deviceLink: DeviceLink) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
database.delete(deviceLinkCache, "$masterHexEncodedPublicKey = ? OR $slaveHexEncodedPublicKey = ?", arrayOf( deviceLink.masterHexEncodedPublicKey, deviceLink.slaveHexEncodedPublicKey ))
|
database.delete(deviceLinkCache, "$masterPublicKey = ? OR $slavePublicKey = ?", arrayOf( deviceLink.masterPublicKey, deviceLink.slavePublicKey ))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUserCount(group: Long, server: String): Int? {
|
fun getUserCount(group: Long, server: String): Int? {
|
||||||
@ -332,8 +332,8 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
|
|
||||||
override fun setSessionRequestTimestamp(publicKey: String, timestamp: Long) {
|
override fun setSessionRequestTimestamp(publicKey: String, timestamp: Long) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val row = wrap(mapOf(LokiAPIDatabase.publicKey to publicKey, LokiAPIDatabase.timestamp to timestamp.toString()))
|
val row = wrap(mapOf(LokiAPIDatabase.sessionRequestPublicKey to publicKey, LokiAPIDatabase.timestamp to timestamp.toString()))
|
||||||
database.insertOrUpdate(sessionRequestTimestampCache, row, "${LokiAPIDatabase.publicKey} = ?", wrap(publicKey))
|
database.insertOrUpdate(sessionRequestTimestampCache, row, "${LokiAPIDatabase.sessionRequestPublicKey} = ?", wrap(publicKey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,34 +16,34 @@ import org.whispersystems.signalservice.loki.protocol.todo.LokiMessageFriendRequ
|
|||||||
class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiMessageDatabaseProtocol {
|
class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiMessageDatabaseProtocol {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val messageFriendRequestTableName = "loki_message_friend_request_database"
|
private val messageFriendRequestTable = "loki_message_friend_request_database"
|
||||||
private val messageThreadMappingTableName = "loki_message_thread_mapping_database"
|
private val messageThreadMappingTable = "loki_message_thread_mapping_database"
|
||||||
private val errorMessageTableName = "loki_error_message_database"
|
private val errorMessageTable = "loki_error_message_database"
|
||||||
private val messageID = "message_id"
|
private val messageID = "message_id"
|
||||||
private val serverID = "server_id"
|
private val serverID = "server_id"
|
||||||
private val friendRequestStatus = "friend_request_status"
|
private val friendRequestStatus = "friend_request_status"
|
||||||
private val threadID = "thread_id"
|
private val threadID = "thread_id"
|
||||||
private val errorMessage = "error_message"
|
private val errorMessage = "error_message"
|
||||||
@JvmStatic val createMessageFriendRequestTableCommand = "CREATE TABLE $messageFriendRequestTableName ($messageID INTEGER PRIMARY KEY, $serverID INTEGER DEFAULT 0, $friendRequestStatus INTEGER DEFAULT 0);"
|
@JvmStatic val createMessageFriendRequestTableCommand = "CREATE TABLE $messageFriendRequestTable ($messageID INTEGER PRIMARY KEY, $serverID INTEGER DEFAULT 0, $friendRequestStatus INTEGER DEFAULT 0);"
|
||||||
@JvmStatic val createMessageToThreadMappingTableCommand = "CREATE TABLE IF NOT EXISTS $messageThreadMappingTableName ($messageID INTEGER PRIMARY KEY, $threadID INTEGER);"
|
@JvmStatic val createMessageToThreadMappingTableCommand = "CREATE TABLE IF NOT EXISTS $messageThreadMappingTable ($messageID INTEGER PRIMARY KEY, $threadID INTEGER);"
|
||||||
@JvmStatic val createErrorMessageTableCommand = "CREATE TABLE IF NOT EXISTS $errorMessageTableName ($messageID INTEGER PRIMARY KEY, $errorMessage STRING);"
|
@JvmStatic val createErrorMessageTableCommand = "CREATE TABLE IF NOT EXISTS $errorMessageTable ($messageID INTEGER PRIMARY KEY, $errorMessage STRING);"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getQuoteServerID(quoteID: Long, quoteeHexEncodedPublicKey: String): Long? {
|
override fun getQuoteServerID(quoteID: Long, quoteePublicKey: String): Long? {
|
||||||
val message = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(quoteID, Address.fromSerialized(quoteeHexEncodedPublicKey))
|
val message = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(quoteID, Address.fromSerialized(quoteePublicKey))
|
||||||
return if (message != null) getServerID(message.getId()) else null
|
return if (message != null) getServerID(message.getId()) else null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getServerID(messageID: Long): Long? {
|
fun getServerID(messageID: Long): Long? {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(messageFriendRequestTableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
return database.get(messageFriendRequestTable, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||||
cursor.getInt(serverID)
|
cursor.getInt(serverID)
|
||||||
}?.toLong()
|
}?.toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMessageID(serverID: Long): Long? {
|
fun getMessageID(serverID: Long): Long? {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(messageFriendRequestTableName, "${Companion.serverID} = ?", arrayOf( serverID.toString() )) { cursor ->
|
return database.get(messageFriendRequestTable, "${Companion.serverID} = ?", arrayOf( serverID.toString() )) { cursor ->
|
||||||
cursor.getInt(messageID)
|
cursor.getInt(messageID)
|
||||||
}?.toLong()
|
}?.toLong()
|
||||||
}
|
}
|
||||||
@ -53,12 +53,12 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
|||||||
val contentValues = ContentValues(2)
|
val contentValues = ContentValues(2)
|
||||||
contentValues.put(Companion.messageID, messageID)
|
contentValues.put(Companion.messageID, messageID)
|
||||||
contentValues.put(Companion.serverID, serverID)
|
contentValues.put(Companion.serverID, serverID)
|
||||||
database.insertOrUpdate(messageFriendRequestTableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
database.insertOrUpdate(messageFriendRequestTable, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOriginalThreadID(messageID: Long): Long {
|
fun getOriginalThreadID(messageID: Long): Long {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(messageThreadMappingTableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
return database.get(messageThreadMappingTable, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||||
cursor.getInt(threadID)
|
cursor.getInt(threadID)
|
||||||
}?.toLong() ?: -1L
|
}?.toLong() ?: -1L
|
||||||
}
|
}
|
||||||
@ -68,12 +68,12 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
|||||||
val contentValues = ContentValues(2)
|
val contentValues = ContentValues(2)
|
||||||
contentValues.put(Companion.messageID, messageID)
|
contentValues.put(Companion.messageID, messageID)
|
||||||
contentValues.put(Companion.threadID, threadID)
|
contentValues.put(Companion.threadID, threadID)
|
||||||
database.insertOrUpdate(messageThreadMappingTableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
database.insertOrUpdate(messageThreadMappingTable, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFriendRequestStatus(messageID: Long): LokiMessageFriendRequestStatus {
|
fun getFriendRequestStatus(messageID: Long): LokiMessageFriendRequestStatus {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
val result = database.get(messageFriendRequestTableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
val result = database.get(messageFriendRequestTable, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||||
cursor.getInt(friendRequestStatus)
|
cursor.getInt(friendRequestStatus)
|
||||||
}
|
}
|
||||||
return if (result != null) {
|
return if (result != null) {
|
||||||
@ -83,12 +83,12 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setFriendRequestStatus(messageID: Long, friendRequestStatus: LokiMessageFriendRequestStatus) {
|
fun setFriendRequestStatus(messageID: Long, friendRequestStatus: LokiMessageFriendRequestStatus) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val contentValues = ContentValues(2)
|
val contentValues = ContentValues(2)
|
||||||
contentValues.put(Companion.messageID, messageID)
|
contentValues.put(Companion.messageID, messageID)
|
||||||
contentValues.put(Companion.friendRequestStatus, friendRequestStatus.rawValue)
|
contentValues.put(Companion.friendRequestStatus, friendRequestStatus.rawValue)
|
||||||
database.insertOrUpdate(messageFriendRequestTableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
database.insertOrUpdate(messageFriendRequestTable, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||||
val threadID = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageID)
|
val threadID = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageID)
|
||||||
notifyConversationListeners(threadID)
|
notifyConversationListeners(threadID)
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
|||||||
|
|
||||||
fun getErrorMessage(messageID: Long): String? {
|
fun getErrorMessage(messageID: Long): String? {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(errorMessageTableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
return database.get(errorMessageTable, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
|
||||||
cursor.getString(errorMessage)
|
cursor.getString(errorMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,6 +109,6 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
|||||||
val contentValues = ContentValues(2)
|
val contentValues = ContentValues(2)
|
||||||
contentValues.put(Companion.messageID, messageID)
|
contentValues.put(Companion.messageID, messageID)
|
||||||
contentValues.put(Companion.errorMessage, errorMessage)
|
contentValues.put(Companion.errorMessage, errorMessage)
|
||||||
database.insertOrUpdate(errorMessageTableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
database.insertOrUpdate(errorMessageTable, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,8 +26,8 @@ import org.whispersystems.signalservice.loki.database.LokiPreKeyBundleDatabasePr
|
|||||||
class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiPreKeyBundleDatabaseProtocol {
|
class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiPreKeyBundleDatabaseProtocol {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val tableName = "loki_pre_key_bundle_database"
|
private val table = "loki_pre_key_bundle_database"
|
||||||
private val hexEncodedPublicKey = "public_key"
|
private val publicKey = "public_key"
|
||||||
private val preKeyID = "pre_key_id"
|
private val preKeyID = "pre_key_id"
|
||||||
private val preKeyPublic = "pre_key_public"
|
private val preKeyPublic = "pre_key_public"
|
||||||
private val signedPreKeyID = "signed_pre_key_id"
|
private val signedPreKeyID = "signed_pre_key_id"
|
||||||
@ -36,16 +36,16 @@ class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) :
|
|||||||
private val identityKey = "identity_key"
|
private val identityKey = "identity_key"
|
||||||
private val deviceID = "device_id"
|
private val deviceID = "device_id"
|
||||||
private val registrationID = "registration_id"
|
private val registrationID = "registration_id"
|
||||||
@JvmStatic val createTableCommand = "CREATE TABLE $tableName (" + "$hexEncodedPublicKey TEXT PRIMARY KEY," + "$preKeyID INTEGER," +
|
@JvmStatic val createTableCommand = "CREATE TABLE $table (" + "$publicKey TEXT PRIMARY KEY," + "$preKeyID INTEGER," +
|
||||||
"$preKeyPublic TEXT NOT NULL," + "$signedPreKeyID INTEGER," + "$signedPreKeyPublic TEXT NOT NULL," +
|
"$preKeyPublic TEXT NOT NULL," + "$signedPreKeyID INTEGER," + "$signedPreKeyPublic TEXT NOT NULL," +
|
||||||
"$signedPreKeySignature TEXT," + "$identityKey TEXT NOT NULL," + "$deviceID INTEGER," + "$registrationID INTEGER" + ");"
|
"$signedPreKeySignature TEXT," + "$identityKey TEXT NOT NULL," + "$deviceID INTEGER," + "$registrationID INTEGER" + ");"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generatePreKeyBundle(hexEncodedPublicKey: String): PreKeyBundle? {
|
fun generatePreKeyBundle(publicKey: String): PreKeyBundle? {
|
||||||
var failureCount = 0
|
var failureCount = 0
|
||||||
while (failureCount < 3) {
|
while (failureCount < 3) {
|
||||||
try {
|
try {
|
||||||
val preKey = generatePreKeyBundle(hexEncodedPublicKey, failureCount > 0) ?: return null
|
val preKey = generatePreKeyBundle(publicKey, failureCount > 0) ?: return null
|
||||||
// Verify the bundle is correct
|
// Verify the bundle is correct
|
||||||
if (!Curve.verifySignature(preKey.identityKey.publicKey, preKey.signedPreKey.serialize(), preKey.signedPreKeySignature)) {
|
if (!Curve.verifySignature(preKey.identityKey.publicKey, preKey.signedPreKey.serialize(), preKey.signedPreKeySignature)) {
|
||||||
throw InvalidKeyException()
|
throw InvalidKeyException()
|
||||||
@ -55,19 +55,19 @@ class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) :
|
|||||||
failureCount += 1
|
failureCount += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.w("Loki", "Failed to generate a valid pre key bundle for: $hexEncodedPublicKey.")
|
Log.w("Loki", "Failed to generate a valid pre key bundle for: $publicKey.")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generatePreKeyBundle(hexEncodedPublicKey: String, forceClean: Boolean): PreKeyBundle? {
|
private fun generatePreKeyBundle(publicKey: String, forceClean: Boolean): PreKeyBundle? {
|
||||||
if (hexEncodedPublicKey.isEmpty()) return null
|
if (publicKey.isEmpty()) return null
|
||||||
var registrationID = TextSecurePreferences.getLocalRegistrationId(context)
|
var registrationID = TextSecurePreferences.getLocalRegistrationId(context)
|
||||||
if (registrationID == 0) {
|
if (registrationID == 0) {
|
||||||
registrationID = KeyHelper.generateRegistrationId(false)
|
registrationID = KeyHelper.generateRegistrationId(false)
|
||||||
TextSecurePreferences.setLocalRegistrationId(context, registrationID)
|
TextSecurePreferences.setLocalRegistrationId(context, registrationID)
|
||||||
}
|
}
|
||||||
val deviceID = SignalServiceAddress.DEFAULT_DEVICE_ID
|
val deviceID = SignalServiceAddress.DEFAULT_DEVICE_ID
|
||||||
val preKeyRecord = DatabaseFactory.getLokiPreKeyRecordDatabase(context).getOrCreatePreKeyRecord(hexEncodedPublicKey)
|
val preKeyRecord = DatabaseFactory.getLokiPreKeyRecordDatabase(context).getOrCreatePreKeyRecord(publicKey)
|
||||||
val identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context)
|
val identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context)
|
||||||
if (!forceClean && TextSecurePreferences.isSignedPreKeyRegistered(context)) {
|
if (!forceClean && TextSecurePreferences.isSignedPreKeyRegistered(context)) {
|
||||||
Log.d("Loki", "A signed pre key has already been registered.")
|
Log.d("Loki", "A signed pre key has already been registered.")
|
||||||
@ -80,9 +80,9 @@ class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) :
|
|||||||
return PreKeyBundle(registrationID, deviceID, preKeyRecord.id, preKeyRecord.keyPair.publicKey, activeSignedPreKey.id, activeSignedPreKey.keyPair.publicKey, activeSignedPreKey.signature, identityKeyPair.publicKey)
|
return PreKeyBundle(registrationID, deviceID, preKeyRecord.id, preKeyRecord.keyPair.publicKey, activeSignedPreKey.id, activeSignedPreKey.keyPair.publicKey, activeSignedPreKey.signature, identityKeyPair.publicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPreKeyBundle(hexEncodedPublicKey: String): PreKeyBundle? {
|
override fun getPreKeyBundle(publicKey: String): PreKeyBundle? {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(tableName, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey )) { cursor ->
|
return database.get(table, "${Companion.publicKey} = ?", arrayOf( publicKey )) { cursor ->
|
||||||
val registrationID = cursor.getInt(registrationID)
|
val registrationID = cursor.getInt(registrationID)
|
||||||
val deviceID = cursor.getInt(deviceID)
|
val deviceID = cursor.getInt(deviceID)
|
||||||
val preKeyID = cursor.getInt(preKeyID)
|
val preKeyID = cursor.getInt(preKeyID)
|
||||||
@ -95,7 +95,7 @@ class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setPreKeyBundle(hexEncodedPublicKey: String, preKeyBundle: PreKeyBundle) {
|
fun setPreKeyBundle(publicKey: String, preKeyBundle: PreKeyBundle) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val values = ContentValues(9)
|
val values = ContentValues(9)
|
||||||
values.put(registrationID, preKeyBundle.registrationId)
|
values.put(registrationID, preKeyBundle.registrationId)
|
||||||
@ -106,20 +106,20 @@ class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) :
|
|||||||
values.put(signedPreKeyPublic, Base64.encodeBytes(preKeyBundle.signedPreKey.serialize()))
|
values.put(signedPreKeyPublic, Base64.encodeBytes(preKeyBundle.signedPreKey.serialize()))
|
||||||
values.put(signedPreKeySignature, Base64.encodeBytes(preKeyBundle.signedPreKeySignature))
|
values.put(signedPreKeySignature, Base64.encodeBytes(preKeyBundle.signedPreKeySignature))
|
||||||
values.put(identityKey, Base64.encodeBytes(preKeyBundle.identityKey.serialize()))
|
values.put(identityKey, Base64.encodeBytes(preKeyBundle.identityKey.serialize()))
|
||||||
values.put(Companion.hexEncodedPublicKey, hexEncodedPublicKey)
|
values.put(Companion.publicKey, publicKey)
|
||||||
database.insertOrUpdate(tableName, values, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey ))
|
database.insertOrUpdate(table, values, "${Companion.publicKey} = ?", arrayOf( publicKey ))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removePreKeyBundle(hexEncodedPublicKey: String) {
|
override fun removePreKeyBundle(publicKey: String) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
database.delete(tableName, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey ))
|
database.delete(table, "${Companion.publicKey} = ?", arrayOf( publicKey ))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasPreKeyBundle(hexEncodedPublicKey: String): Boolean {
|
fun hasPreKeyBundle(publicKey: String): Boolean {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
return try {
|
return try {
|
||||||
cursor = database.query(tableName, null, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey ), null, null, null)
|
cursor = database.query(table, null, "${Companion.publicKey} = ?", arrayOf( publicKey ), null, null, null)
|
||||||
cursor != null && cursor.count > 0
|
cursor != null && cursor.count > 0
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
false
|
false
|
||||||
|
@ -14,38 +14,38 @@ import org.whispersystems.signalservice.loki.database.LokiPreKeyRecordDatabasePr
|
|||||||
class LokiPreKeyRecordDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiPreKeyRecordDatabaseProtocol {
|
class LokiPreKeyRecordDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiPreKeyRecordDatabaseProtocol {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val tableName = "loki_pre_key_record_database"
|
private val table = "loki_pre_key_record_database"
|
||||||
private val hexEncodedPublicKey = "public_key"
|
private val publicKey = "public_key"
|
||||||
private val preKeyID = "pre_key_id"
|
private val preKeyID = "pre_key_id"
|
||||||
@JvmStatic val createTableCommand = "CREATE TABLE $tableName ($hexEncodedPublicKey TEXT PRIMARY KEY, $preKeyID INTEGER);"
|
@JvmStatic val createTableCommand = "CREATE TABLE $table ($publicKey TEXT PRIMARY KEY, $preKeyID INTEGER);"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasPreKey(hexEncodedPublicKey: String): Boolean {
|
fun hasPreKey(publicKey: String): Boolean {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(tableName, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey )) { it.count > 0 } ?: false
|
return database.get(table, "${Companion.publicKey} = ?", arrayOf( publicKey )) { it.count > 0 } ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPreKeyRecord(hexEncodedPublicKey: String): PreKeyRecord? {
|
override fun getPreKeyRecord(publicKey: String): PreKeyRecord? {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(tableName, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey )) { cursor ->
|
return database.get(table, "${Companion.publicKey} = ?", arrayOf( publicKey )) { cursor ->
|
||||||
val preKeyID = cursor.getInt(preKeyID)
|
val preKeyID = cursor.getInt(preKeyID)
|
||||||
PreKeyUtil.loadPreKey(context, preKeyID)
|
PreKeyUtil.loadPreKey(context, preKeyID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOrCreatePreKeyRecord(hexEncodedPublicKey: String): PreKeyRecord {
|
fun getOrCreatePreKeyRecord(publicKey: String): PreKeyRecord {
|
||||||
return getPreKeyRecord(hexEncodedPublicKey) ?: generateAndStorePreKeyRecord(hexEncodedPublicKey)
|
return getPreKeyRecord(publicKey) ?: generateAndStorePreKeyRecord(publicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateAndStorePreKeyRecord(hexEncodedPublicKey: String): PreKeyRecord {
|
private fun generateAndStorePreKeyRecord(publicKey: String): PreKeyRecord {
|
||||||
val records = PreKeyUtil.generatePreKeyRecords(context, 1)
|
val records = PreKeyUtil.generatePreKeyRecords(context, 1)
|
||||||
PreKeyUtil.storePreKeyRecords(context, records)
|
PreKeyUtil.storePreKeyRecords(context, records)
|
||||||
val record = records.first()
|
val record = records.first()
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val values = ContentValues(2)
|
val values = ContentValues(2)
|
||||||
values.put(Companion.hexEncodedPublicKey, hexEncodedPublicKey)
|
values.put(Companion.publicKey, publicKey)
|
||||||
values.put(preKeyID, record.id)
|
values.put(preKeyID, record.id)
|
||||||
database.insertOrUpdate(tableName, values, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey ))
|
database.insertOrUpdate(table, values, "${Companion.publicKey} = ?", arrayOf( publicKey ))
|
||||||
return record
|
return record
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,9 +11,9 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
|||||||
import org.thoughtcrime.securesms.loki.utilities.*
|
import org.thoughtcrime.securesms.loki.utilities.*
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.libsignal.loki.LokiSessionResetStatus
|
import org.whispersystems.libsignal.loki.SessionResetStatus
|
||||||
import org.whispersystems.signalservice.internal.util.JsonUtil
|
import org.whispersystems.signalservice.internal.util.JsonUtil
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||||
import org.whispersystems.signalservice.loki.database.LokiThreadDatabaseProtocol
|
import org.whispersystems.signalservice.loki.database.LokiThreadDatabaseProtocol
|
||||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||||
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
|
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
|
||||||
@ -22,16 +22,16 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
|||||||
var delegate: LokiThreadDatabaseDelegate? = null
|
var delegate: LokiThreadDatabaseDelegate? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val friendRequestTableName = "loki_thread_friend_request_database"
|
private val friendRequestTable = "loki_thread_friend_request_database"
|
||||||
private val sessionResetTableName = "loki_thread_session_reset_database"
|
private val sessionResetTable = "loki_thread_session_reset_database"
|
||||||
val publicChatTableName = "loki_public_chat_database"
|
val publicChatTable = "loki_public_chat_database"
|
||||||
val threadID = "thread_id"
|
val threadID = "thread_id"
|
||||||
private val friendRequestStatus = "friend_request_status"
|
private val friendRequestStatus = "friend_request_status"
|
||||||
private val sessionResetStatus = "session_reset_status"
|
private val sessionResetStatus = "session_reset_status"
|
||||||
val publicChat = "public_chat"
|
val publicChat = "public_chat"
|
||||||
@JvmStatic val createFriendRequestTableCommand = "CREATE TABLE $friendRequestTableName ($threadID INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);"
|
@JvmStatic val createFriendRequestTableCommand = "CREATE TABLE $friendRequestTable ($threadID INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);"
|
||||||
@JvmStatic val createSessionResetTableCommand = "CREATE TABLE $sessionResetTableName ($threadID INTEGER PRIMARY KEY, $sessionResetStatus INTEGER DEFAULT 0);"
|
@JvmStatic val createSessionResetTableCommand = "CREATE TABLE $sessionResetTable ($threadID INTEGER PRIMARY KEY, $sessionResetStatus INTEGER DEFAULT 0);"
|
||||||
@JvmStatic val createPublicChatTableCommand = "CREATE TABLE $publicChatTableName ($threadID INTEGER PRIMARY KEY, $publicChat TEXT);"
|
@JvmStatic val createPublicChatTableCommand = "CREATE TABLE $publicChatTable ($threadID INTEGER PRIMARY KEY, $publicChat TEXT);"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getThreadID(hexEncodedPublicKey: String): Long {
|
override fun getThreadID(hexEncodedPublicKey: String): Long {
|
||||||
@ -49,7 +49,7 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
|||||||
val recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID)
|
val recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID)
|
||||||
if (recipient != null && recipient.isGroupRecipient) { return LokiThreadFriendRequestStatus.FRIENDS; }
|
if (recipient != null && recipient.isGroupRecipient) { return LokiThreadFriendRequestStatus.FRIENDS; }
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
val result = database.get(friendRequestTableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
|
val result = database.get(friendRequestTable, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
|
||||||
cursor.getInt(friendRequestStatus)
|
cursor.getInt(friendRequestStatus)
|
||||||
}
|
}
|
||||||
return if (result != null) {
|
return if (result != null) {
|
||||||
@ -59,59 +59,53 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setFriendRequestStatus(threadID: Long, friendRequestStatus: LokiThreadFriendRequestStatus) {
|
fun setFriendRequestStatus(threadID: Long, friendRequestStatus: LokiThreadFriendRequestStatus) {
|
||||||
if (threadID < 0) { return }
|
if (threadID < 0) { return }
|
||||||
Log.d("Loki", "Setting FR status for thread with ID $threadID to $friendRequestStatus.")
|
Log.d("Loki", "Setting FR status for thread with ID $threadID to $friendRequestStatus.")
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val contentValues = ContentValues(2)
|
val contentValues = ContentValues(2)
|
||||||
contentValues.put(Companion.threadID, threadID)
|
contentValues.put(Companion.threadID, threadID)
|
||||||
contentValues.put(Companion.friendRequestStatus, friendRequestStatus.rawValue)
|
contentValues.put(Companion.friendRequestStatus, friendRequestStatus.rawValue)
|
||||||
database.insertOrUpdate(friendRequestTableName, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
database.insertOrUpdate(friendRequestTable, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
||||||
notifyConversationListListeners()
|
notifyConversationListListeners()
|
||||||
notifyConversationListeners(threadID)
|
notifyConversationListeners(threadID)
|
||||||
delegate?.handleThreadFriendRequestStatusChanged(threadID)
|
delegate?.handleThreadFriendRequestStatusChanged(threadID)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasPendingFriendRequest(threadID: Long): Boolean {
|
fun getSessionResetStatus(hexEncodedPublicKey: String): SessionResetStatus {
|
||||||
val friendRequestStatus = getFriendRequestStatus(threadID)
|
|
||||||
return friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENDING || friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT
|
|
||||||
|| friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_RECEIVED
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSessionResetStatus(hexEncodedPublicKey: String): LokiSessionResetStatus {
|
|
||||||
val threadID = getThreadID(hexEncodedPublicKey)
|
val threadID = getThreadID(hexEncodedPublicKey)
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
val result = database.get(sessionResetTableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
|
val result = database.get(sessionResetTable, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
|
||||||
cursor.getInt(sessionResetStatus)
|
cursor.getInt(sessionResetStatus)
|
||||||
}
|
}
|
||||||
return if (result != null) {
|
return if (result != null) {
|
||||||
LokiSessionResetStatus.values().first { it.rawValue == result }
|
SessionResetStatus.values().first { it.rawValue == result }
|
||||||
} else {
|
} else {
|
||||||
LokiSessionResetStatus.NONE
|
SessionResetStatus.NONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSessionResetStatus(hexEncodedPublicKey: String, sessionResetStatus: LokiSessionResetStatus) {
|
fun setSessionResetStatus(hexEncodedPublicKey: String, sessionResetStatus: SessionResetStatus) {
|
||||||
val threadID = getThreadID(hexEncodedPublicKey)
|
val threadID = getThreadID(hexEncodedPublicKey)
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val contentValues = ContentValues(2)
|
val contentValues = ContentValues(2)
|
||||||
contentValues.put(Companion.threadID, threadID)
|
contentValues.put(Companion.threadID, threadID)
|
||||||
contentValues.put(Companion.sessionResetStatus, sessionResetStatus.rawValue)
|
contentValues.put(Companion.sessionResetStatus, sessionResetStatus.rawValue)
|
||||||
database.insertOrUpdate(sessionResetTableName, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
database.insertOrUpdate(sessionResetTable, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
||||||
notifyConversationListListeners()
|
notifyConversationListListeners()
|
||||||
notifyConversationListeners(threadID)
|
notifyConversationListeners(threadID)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllPublicChats(): Map<Long, LokiPublicChat> {
|
fun getAllPublicChats(): Map<Long, PublicChat> {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
val result = mutableMapOf<Long, LokiPublicChat>()
|
val result = mutableMapOf<Long, PublicChat>()
|
||||||
try {
|
try {
|
||||||
cursor = database.rawQuery("select * from $publicChatTableName", null)
|
cursor = database.rawQuery("select * from $publicChatTable", null)
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
val threadID = cursor.getLong(threadID)
|
val threadID = cursor.getLong(threadID)
|
||||||
val string = cursor.getString(publicChat)
|
val string = cursor.getString(publicChat)
|
||||||
val publicChat = LokiPublicChat.fromJSON(string)
|
val publicChat = PublicChat.fromJSON(string)
|
||||||
if (publicChat != null) { result[threadID] = publicChat }
|
if (publicChat != null) { result[threadID] = publicChat }
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -126,31 +120,31 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
|||||||
return getAllPublicChats().values.fold(setOf()) { set, chat -> set.plus(chat.server) }
|
return getAllPublicChats().values.fold(setOf()) { set, chat -> set.plus(chat.server) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPublicChat(threadID: Long): LokiPublicChat? {
|
override fun getPublicChat(threadID: Long): PublicChat? {
|
||||||
if (threadID < 0) { return null }
|
if (threadID < 0) { return null }
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(publicChatTableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
|
return database.get(publicChatTable, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
|
||||||
val publicChatAsJSON = cursor.getString(publicChat)
|
val publicChatAsJSON = cursor.getString(publicChat)
|
||||||
LokiPublicChat.fromJSON(publicChatAsJSON)
|
PublicChat.fromJSON(publicChatAsJSON)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setPublicChat(publicChat: LokiPublicChat, threadID: Long) {
|
override fun setPublicChat(publicChat: PublicChat, threadID: Long) {
|
||||||
if (threadID < 0) { return }
|
if (threadID < 0) { return }
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val contentValues = ContentValues(2)
|
val contentValues = ContentValues(2)
|
||||||
contentValues.put(Companion.threadID, threadID)
|
contentValues.put(Companion.threadID, threadID)
|
||||||
contentValues.put(Companion.publicChat, JsonUtil.toJson(publicChat.toJSON()))
|
contentValues.put(Companion.publicChat, JsonUtil.toJson(publicChat.toJSON()))
|
||||||
database.insertOrUpdate(publicChatTableName, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
database.insertOrUpdate(publicChatTable, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun removePublicChat(threadID: Long) {
|
override fun removePublicChat(threadID: Long) {
|
||||||
databaseHelper.writableDatabase.delete(publicChatTableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
databaseHelper.writableDatabase.delete(publicChatTable, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addSessionRestoreDevice(threadID: Long, hexEncodedPublicKey: String) {
|
fun addSessionRestoreDevice(threadID: Long, publicKey: String) {
|
||||||
val devices = getSessionRestoreDevices(threadID).toMutableSet()
|
val devices = getSessionRestoreDevices(threadID).toMutableSet()
|
||||||
if (devices.add(hexEncodedPublicKey)) {
|
if (devices.add(publicKey)) {
|
||||||
TextSecurePreferences.setStringPreference(context, "session_restore_devices_$threadID", devices.joinToString(","))
|
TextSecurePreferences.setStringPreference(context, "session_restore_devices_$threadID", devices.joinToString(","))
|
||||||
delegate?.handleSessionRestoreDevicesChanged(threadID)
|
delegate?.handleSessionRestoreDevicesChanged(threadID)
|
||||||
}
|
}
|
||||||
|
@ -20,60 +20,60 @@ class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database
|
|||||||
private val displayName = "display_name"
|
private val displayName = "display_name"
|
||||||
// Display name cache
|
// Display name cache
|
||||||
private val displayNameTable = "loki_user_display_name_database"
|
private val displayNameTable = "loki_user_display_name_database"
|
||||||
private val hexEncodedPublicKey = "hex_encoded_public_key"
|
private val publicKey = "hex_encoded_public_key"
|
||||||
@JvmStatic val createDisplayNameTableCommand = "CREATE TABLE $displayNameTable ($hexEncodedPublicKey TEXT PRIMARY KEY, $displayName TEXT);"
|
@JvmStatic val createDisplayNameTableCommand = "CREATE TABLE $displayNameTable ($publicKey TEXT PRIMARY KEY, $displayName TEXT);"
|
||||||
// Server display name cache
|
// Server display name cache
|
||||||
private val serverDisplayNameTable = "loki_user_server_display_name_database"
|
private val serverDisplayNameTable = "loki_user_server_display_name_database"
|
||||||
private val serverID = "server_id"
|
private val serverID = "server_id"
|
||||||
@JvmStatic val createServerDisplayNameTableCommand = "CREATE TABLE $serverDisplayNameTable ($hexEncodedPublicKey TEXT, $serverID TEXT, $displayName TEXT, PRIMARY KEY ($hexEncodedPublicKey, $serverID));"
|
@JvmStatic val createServerDisplayNameTableCommand = "CREATE TABLE $serverDisplayNameTable ($publicKey TEXT, $serverID TEXT, $displayName TEXT, PRIMARY KEY ($publicKey, $serverID));"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDisplayName(hexEncodedPublicKey: String): String? {
|
override fun getDisplayName(publicKey: String): String? {
|
||||||
if (hexEncodedPublicKey == TextSecurePreferences.getLocalNumber(context)) {
|
if (publicKey == TextSecurePreferences.getLocalNumber(context)) {
|
||||||
return TextSecurePreferences.getProfileName(context)
|
return TextSecurePreferences.getProfileName(context)
|
||||||
} else {
|
} else {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(displayNameTable, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey )) { cursor ->
|
return database.get(displayNameTable, "${Companion.publicKey} = ?", arrayOf( publicKey )) { cursor ->
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(displayName))
|
cursor.getString(cursor.getColumnIndexOrThrow(displayName))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setDisplayName(hexEncodedPublicKey: String, displayName: String) {
|
fun setDisplayName(publicKey: String, displayName: String) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val row = ContentValues(2)
|
val row = ContentValues(2)
|
||||||
row.put(Companion.hexEncodedPublicKey, hexEncodedPublicKey)
|
row.put(Companion.publicKey, publicKey)
|
||||||
row.put(Companion.displayName, displayName)
|
row.put(Companion.displayName, displayName)
|
||||||
database.insertOrUpdate(displayNameTable, row, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey ))
|
database.insertOrUpdate(displayNameTable, row, "${Companion.publicKey} = ?", arrayOf( publicKey ))
|
||||||
Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false).notifyListeners()
|
Recipient.from(context, Address.fromSerialized(publicKey), false).notifyListeners()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getServerDisplayName(serverID: String, hexEncodedPublicKey: String): String? {
|
override fun getServerDisplayName(serverID: String, publicKey: String): String? {
|
||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(serverDisplayNameTable, "${Companion.hexEncodedPublicKey} = ? AND ${Companion.serverID} = ?", arrayOf( hexEncodedPublicKey, serverID )) { cursor ->
|
return database.get(serverDisplayNameTable, "${Companion.publicKey} = ? AND ${Companion.serverID} = ?", arrayOf( publicKey, serverID )) { cursor ->
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(displayName))
|
cursor.getString(cursor.getColumnIndexOrThrow(displayName))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setServerDisplayName(serverID: String, hexEncodedPublicKey: String, displayName: String) {
|
fun setServerDisplayName(serverID: String, publicKey: String, displayName: String) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val values = ContentValues(3)
|
val values = ContentValues(3)
|
||||||
values.put(Companion.serverID, serverID)
|
values.put(Companion.serverID, serverID)
|
||||||
values.put(Companion.hexEncodedPublicKey, hexEncodedPublicKey)
|
values.put(Companion.publicKey, publicKey)
|
||||||
values.put(Companion.displayName, displayName)
|
values.put(Companion.displayName, displayName)
|
||||||
try {
|
try {
|
||||||
database.insertWithOnConflict(serverDisplayNameTable, null, values, SQLiteDatabase.CONFLICT_REPLACE)
|
database.insertWithOnConflict(serverDisplayNameTable, null, values, SQLiteDatabase.CONFLICT_REPLACE)
|
||||||
Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false).notifyListeners()
|
Recipient.from(context, Address.fromSerialized(publicKey), false).notifyListeners()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Loki", "Couldn't save server display name due to exception: $e.")
|
Log.d("Loki", "Couldn't save server display name due to exception: $e.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getProfilePictureURL(hexEncodedPublicKey: String): String? {
|
override fun getProfilePictureURL(publicKey: String): String? {
|
||||||
return if (hexEncodedPublicKey == TextSecurePreferences.getLocalNumber(context)) {
|
return if (publicKey == TextSecurePreferences.getLocalNumber(context)) {
|
||||||
TextSecurePreferences.getProfilePictureURL(context)
|
TextSecurePreferences.getProfilePictureURL(context)
|
||||||
} else {
|
} else {
|
||||||
Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false).resolve().profileAvatar
|
Recipient.from(context, Address.fromSerialized(publicKey), false).resolve().profileAvatar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.loki.utilities.toPx
|
|||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.thoughtcrime.securesms.util.Util
|
import org.thoughtcrime.securesms.util.Util
|
||||||
import org.whispersystems.signalservice.loki.api.SnodeAPI
|
import org.whispersystems.signalservice.loki.api.SnodeAPI
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
||||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
||||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLinkingSession
|
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLinkingSession
|
||||||
@ -52,7 +52,7 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun requestUserAuthorization(deviceLink: DeviceLink) {
|
override fun requestUserAuthorization(deviceLink: DeviceLink) {
|
||||||
if (deviceLink.type != DeviceLink.Type.REQUEST || deviceLink.masterHexEncodedPublicKey != TextSecurePreferences.getLocalNumber(context!!) || this.deviceLink != null) { return }
|
if (deviceLink.type != DeviceLink.Type.REQUEST || deviceLink.masterPublicKey != TextSecurePreferences.getLocalNumber(context!!) || this.deviceLink != null) { return }
|
||||||
Util.runOnMain {
|
Util.runOnMain {
|
||||||
this.deviceLink = deviceLink
|
this.deviceLink = deviceLink
|
||||||
contentView.qrCodeImageView.visibility = View.GONE
|
contentView.qrCodeImageView.visibility = View.GONE
|
||||||
@ -62,7 +62,7 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
|
|||||||
contentView.titleTextView.text = resources.getString(R.string.dialog_link_device_master_mode_title_2)
|
contentView.titleTextView.text = resources.getString(R.string.dialog_link_device_master_mode_title_2)
|
||||||
contentView.explanationTextView.text = resources.getString(R.string.dialog_link_device_master_mode_explanation_2)
|
contentView.explanationTextView.text = resources.getString(R.string.dialog_link_device_master_mode_explanation_2)
|
||||||
contentView.mnemonicTextView.visibility = View.VISIBLE
|
contentView.mnemonicTextView.visibility = View.VISIBLE
|
||||||
contentView.mnemonicTextView.text = MnemonicUtilities.getFirst3Words(MnemonicCodec(languageFileDirectory), deviceLink.slaveHexEncodedPublicKey)
|
contentView.mnemonicTextView.text = MnemonicUtilities.getFirst3Words(MnemonicCodec(languageFileDirectory), deviceLink.slavePublicKey)
|
||||||
contentView.authorizeButton.visibility = View.VISIBLE
|
contentView.authorizeButton.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
|
|||||||
contentView.cancelButton.visibility = View.GONE
|
contentView.cancelButton.visibility = View.GONE
|
||||||
contentView.authorizeButton.visibility = View.GONE
|
contentView.authorizeButton.visibility = View.GONE
|
||||||
}
|
}
|
||||||
LokiFileServerAPI.shared.addDeviceLink(deviceLink).bind(SnodeAPI.sharedContext) {
|
FileServerAPI.shared.addDeviceLink(deviceLink).bind(SnodeAPI.sharedContext) {
|
||||||
MultiDeviceProtocol.signAndSendDeviceLinkMessage(context!!, deviceLink)
|
MultiDeviceProtocol.signAndSendDeviceLinkMessage(context!!, deviceLink)
|
||||||
}.success {
|
}.success {
|
||||||
TextSecurePreferences.setMultiDevice(context!!, true)
|
TextSecurePreferences.setMultiDevice(context!!, true)
|
||||||
@ -92,8 +92,8 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
|
|||||||
delegate?.onDeviceLinkRequestAuthorized()
|
delegate?.onDeviceLinkRequestAuthorized()
|
||||||
dismiss()
|
dismiss()
|
||||||
}.fail {
|
}.fail {
|
||||||
LokiFileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem
|
FileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem
|
||||||
DatabaseFactory.getLokiPreKeyBundleDatabase(context!!).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey)
|
DatabaseFactory.getLokiPreKeyBundleDatabase(context!!).removePreKeyBundle(deviceLink.slavePublicKey)
|
||||||
}.failUi {
|
}.failUi {
|
||||||
delegate?.onDeviceLinkAuthorizationFailed()
|
delegate?.onDeviceLinkAuthorizationFailed()
|
||||||
dismiss()
|
dismiss()
|
||||||
@ -104,7 +104,7 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
|
|||||||
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
||||||
DeviceLinkingSession.shared.removeListener(this)
|
DeviceLinkingSession.shared.removeListener(this)
|
||||||
if (deviceLink != null) {
|
if (deviceLink != null) {
|
||||||
DatabaseFactory.getLokiPreKeyBundleDatabase(context).removePreKeyBundle(deviceLink!!.slaveHexEncodedPublicKey)
|
DatabaseFactory.getLokiPreKeyBundleDatabase(context).removePreKeyBundle(deviceLink!!.slavePublicKey)
|
||||||
}
|
}
|
||||||
dismiss()
|
dismiss()
|
||||||
delegate?.onDeviceLinkCanceled()
|
delegate?.onDeviceLinkCanceled()
|
||||||
|
@ -41,7 +41,7 @@ class LinkDeviceSlaveModeDialog : DialogFragment(), DeviceLinkingSessionListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
||||||
if (deviceLink.type != DeviceLink.Type.AUTHORIZATION || deviceLink.slaveHexEncodedPublicKey != TextSecurePreferences.getLocalNumber(context!!) || this.deviceLink != null) { return }
|
if (deviceLink.type != DeviceLink.Type.AUTHORIZATION || deviceLink.slavePublicKey != TextSecurePreferences.getLocalNumber(context!!) || this.deviceLink != null) { return }
|
||||||
Util.runOnMain {
|
Util.runOnMain {
|
||||||
this.deviceLink = deviceLink
|
this.deviceLink = deviceLink
|
||||||
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
||||||
|
@ -18,7 +18,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceContent
|
|||||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup
|
import org.whispersystems.signalservice.api.messages.SignalServiceGroup
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||||
import org.whispersystems.signalservice.loki.api.SnodeAPI
|
import org.whispersystems.signalservice.loki.api.SnodeAPI
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ object ClosedGroupsProtocol {
|
|||||||
if (!conversation.address.isClosedGroup || groupID == null) { return false }
|
if (!conversation.address.isClosedGroup || groupID == null) { return false }
|
||||||
// A closed group's members should never include slave devices
|
// A closed group's members should never include slave devices
|
||||||
val senderPublicKey = content.sender
|
val senderPublicKey = content.sender
|
||||||
LokiFileServerAPI.shared.getDeviceLinks(senderPublicKey).timeout(6000).get()
|
FileServerAPI.shared.getDeviceLinks(senderPublicKey).timeout(6000).get()
|
||||||
val senderMasterPublicKey = MultiDeviceProtocol.shared.getMasterDevice(senderPublicKey)
|
val senderMasterPublicKey = MultiDeviceProtocol.shared.getMasterDevice(senderPublicKey)
|
||||||
val publicKeyToCheckFor = senderMasterPublicKey ?: senderPublicKey
|
val publicKeyToCheckFor = senderMasterPublicKey ?: senderPublicKey
|
||||||
val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupID, true)
|
val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupID, true)
|
||||||
@ -57,7 +57,7 @@ object ClosedGroupsProtocol {
|
|||||||
} else {
|
} else {
|
||||||
// A closed group's members should never include slave devices
|
// A closed group's members should never include slave devices
|
||||||
val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupID, false)
|
val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupID, false)
|
||||||
return LokiFileServerAPI.shared.getDeviceLinks(members.map { it.address.serialize() }.toSet()).map {
|
return FileServerAPI.shared.getDeviceLinks(members.map { it.address.serialize() }.toSet()).map {
|
||||||
val result = members.flatMap { member ->
|
val result = members.flatMap { member ->
|
||||||
MultiDeviceProtocol.shared.getAllLinkedDevices(member.address.serialize()).map { Address.fromSerialized(it) }
|
MultiDeviceProtocol.shared.getAllLinkedDevices(member.address.serialize()).map { Address.fromSerialized(it) }
|
||||||
}.toMutableSet()
|
}.toMutableSet()
|
||||||
@ -106,7 +106,7 @@ object ClosedGroupsProtocol {
|
|||||||
allDevices.remove(userPublicKey)
|
allDevices.remove(userPublicKey)
|
||||||
}
|
}
|
||||||
for (device in allDevices) {
|
for (device in allDevices) {
|
||||||
ApplicationContext.getInstance(context).sendSessionRequest(device)
|
ApplicationContext.getInstance(context).sendSessionRequestIfNeeded(device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -140,7 +140,6 @@ object FriendRequestProtocol {
|
|||||||
fun handleFriendRequestAcceptanceIfNeeded(context: Context, publicKey: String, content: SignalServiceContent) {
|
fun handleFriendRequestAcceptanceIfNeeded(context: Context, publicKey: String, content: SignalServiceContent) {
|
||||||
// If we get an envelope that isn't a friend request, then we can infer that we had to use
|
// If we get an envelope that isn't a friend request, then we can infer that we had to use
|
||||||
// Signal cipher decryption and thus that we have a session with the other person.
|
// Signal cipher decryption and thus that we have a session with the other person.
|
||||||
if (content.isFriendRequest) { return }
|
|
||||||
val recipient = recipient(context, publicKey)
|
val recipient = recipient(context, publicKey)
|
||||||
// Friend requests don't apply to groups
|
// Friend requests don't apply to groups
|
||||||
if (recipient.isGroupRecipient) { return }
|
if (recipient.isGroupRecipient) { return }
|
||||||
@ -200,7 +199,6 @@ object FriendRequestProtocol {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun handleFriendRequestMessageIfNeeded(context: Context, publicKey: String, content: SignalServiceContent) {
|
fun handleFriendRequestMessageIfNeeded(context: Context, publicKey: String, content: SignalServiceContent) {
|
||||||
if (!content.isFriendRequest) { return }
|
|
||||||
val recipient = recipient(context, publicKey)
|
val recipient = recipient(context, publicKey)
|
||||||
// Friend requests don't apply to groups
|
// Friend requests don't apply to groups
|
||||||
if (recipient.isGroupRecipient) { return }
|
if (recipient.isGroupRecipient) { return }
|
||||||
@ -241,7 +239,7 @@ object FriendRequestProtocol {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isFriendRequestFromBeforeRestoration(context: Context, content: SignalServiceContent): Boolean {
|
fun isFriendRequestFromBeforeRestoration(context: Context, content: SignalServiceContent): Boolean {
|
||||||
return content.isFriendRequest && content.timestamp < TextSecurePreferences.getRestorationTime(context)
|
return content.timestamp < TextSecurePreferences.getRestorationTime(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -3,30 +3,30 @@ package org.thoughtcrime.securesms.loki.protocol
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.whispersystems.libsignal.loki.LokiSessionResetProtocol
|
import org.whispersystems.libsignal.loki.SessionResetProtocol
|
||||||
import org.whispersystems.libsignal.loki.LokiSessionResetStatus
|
import org.whispersystems.libsignal.loki.SessionResetStatus
|
||||||
import org.whispersystems.libsignal.protocol.PreKeySignalMessage
|
import org.whispersystems.libsignal.protocol.PreKeySignalMessage
|
||||||
|
|
||||||
class LokiSessionResetImplementation(private val context: Context) : LokiSessionResetProtocol {
|
class LokiSessionResetImplementation(private val context: Context) : SessionResetProtocol {
|
||||||
|
|
||||||
override fun getSessionResetStatus(hexEncodedPublicKey: String): LokiSessionResetStatus {
|
override fun getSessionResetStatus(publicKey: String): SessionResetStatus {
|
||||||
return DatabaseFactory.getLokiThreadDatabase(context).getSessionResetStatus(hexEncodedPublicKey)
|
return DatabaseFactory.getLokiThreadDatabase(context).getSessionResetStatus(publicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setSessionResetStatus(hexEncodedPublicKey: String, sessionResetStatus: LokiSessionResetStatus) {
|
override fun setSessionResetStatus(publicKey: String, sessionResetStatus: SessionResetStatus) {
|
||||||
return DatabaseFactory.getLokiThreadDatabase(context).setSessionResetStatus(hexEncodedPublicKey, sessionResetStatus)
|
return DatabaseFactory.getLokiThreadDatabase(context).setSessionResetStatus(publicKey, sessionResetStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNewSessionAdopted(hexEncodedPublicKey: String, oldSessionResetStatus: LokiSessionResetStatus) {
|
override fun onNewSessionAdopted(publicKey: String, oldSessionResetStatus: SessionResetStatus) {
|
||||||
if (oldSessionResetStatus == LokiSessionResetStatus.IN_PROGRESS) {
|
if (oldSessionResetStatus == SessionResetStatus.IN_PROGRESS) {
|
||||||
val ephemeralMessage = EphemeralMessage.create(hexEncodedPublicKey)
|
val ephemeralMessage = EphemeralMessage.create(publicKey)
|
||||||
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(ephemeralMessage))
|
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(ephemeralMessage))
|
||||||
}
|
}
|
||||||
// TODO: Show session reset succeed message
|
// TODO: Show session reset succeed message
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun validatePreKeySignalMessage(sender: String, message: PreKeySignalMessage) {
|
override fun validatePreKeySignalMessage(publicKey: String, message: PreKeySignalMessage) {
|
||||||
val preKeyRecord = DatabaseFactory.getLokiPreKeyRecordDatabase(context).getPreKeyRecord(sender) ?: return
|
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
|
// 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." }
|
check(preKeyRecord.id == (message.preKeyId ?: -1)) { "Received a background message from an unknown source." }
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import org.thoughtcrime.securesms.logging.Log
|
|||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender
|
import org.whispersystems.signalservice.api.SignalServiceMessageSender
|
||||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage
|
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ class MultiDeviceOpenGroupUpdateJob private constructor(parameters: Parameters)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Gather open groups
|
// Gather open groups
|
||||||
val openGroups = mutableListOf<LokiPublicChat>()
|
val openGroups = mutableListOf<PublicChat>()
|
||||||
DatabaseFactory.getGroupDatabase(context).groups.use { reader ->
|
DatabaseFactory.getGroupDatabase(context).groups.use { reader ->
|
||||||
while (true) {
|
while (true) {
|
||||||
val record = reader.next ?: return@use
|
val record = reader.next ?: return@use
|
||||||
|
@ -18,7 +18,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences
|
|||||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent
|
import org.whispersystems.signalservice.api.messages.SignalServiceContent
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
||||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
||||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLinkingSession
|
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLinkingSession
|
||||||
@ -80,7 +80,7 @@ object MultiDeviceProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val publicKey = recipient.address.serialize()
|
val publicKey = recipient.address.serialize()
|
||||||
LokiFileServerAPI.shared.getDeviceLinks(publicKey).success {
|
FileServerAPI.shared.getDeviceLinks(publicKey).success {
|
||||||
val devices = MultiDeviceProtocol.shared.getAllLinkedDevices(publicKey)
|
val devices = MultiDeviceProtocol.shared.getAllLinkedDevices(publicKey)
|
||||||
val jobs = devices.map { sendMessagePushToDevice(context, recipient(context, it), messageID, messageType, isEndSession) }
|
val jobs = devices.map { sendMessagePushToDevice(context, recipient(context, it), messageID, messageType, isEndSession) }
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@ -105,7 +105,7 @@ object MultiDeviceProtocol {
|
|||||||
// A request should include a pre key bundle. An authorization should be a normal message.
|
// A request should include a pre key bundle. An authorization should be a normal message.
|
||||||
if (deviceLink.type == DeviceLink.Type.REQUEST) {
|
if (deviceLink.type == DeviceLink.Type.REQUEST) {
|
||||||
val preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.number)
|
val preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.number)
|
||||||
message.asFriendRequest(true).withPreKeyBundle(preKeyBundle)
|
message.withPreKeyBundle(preKeyBundle)
|
||||||
} else {
|
} else {
|
||||||
// Include the user's profile key so that the slave device can get the user's profile picture
|
// Include the user's profile key so that the slave device can get the user's profile picture
|
||||||
message.withProfileKey(ProfileKeyUtil.getProfileKey(context))
|
message.withProfileKey(ProfileKeyUtil.getProfileKey(context))
|
||||||
@ -135,7 +135,7 @@ object MultiDeviceProtocol {
|
|||||||
return Promise.ofFail(Exception("Failed to sign device link."))
|
return Promise.ofFail(Exception("Failed to sign device link."))
|
||||||
}
|
}
|
||||||
return retryIfNeeded(8) {
|
return retryIfNeeded(8) {
|
||||||
sendDeviceLinkMessage(context, deviceLink.slaveHexEncodedPublicKey, signedDeviceLink)
|
sendDeviceLinkMessage(context, deviceLink.slavePublicKey, signedDeviceLink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ object MultiDeviceProtocol {
|
|||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||||
if (deviceLink.type == DeviceLink.Type.REQUEST) {
|
if (deviceLink.type == DeviceLink.Type.REQUEST) {
|
||||||
handleDeviceLinkRequestMessage(context, deviceLink, content)
|
handleDeviceLinkRequestMessage(context, deviceLink, content)
|
||||||
} else if (deviceLink.slaveHexEncodedPublicKey == userPublicKey) {
|
} else if (deviceLink.slavePublicKey == userPublicKey) {
|
||||||
handleDeviceLinkAuthorizedMessage(context, deviceLink, content)
|
handleDeviceLinkAuthorizedMessage(context, deviceLink, content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,10 +158,10 @@ object MultiDeviceProtocol {
|
|||||||
} else if (isRequest && TextSecurePreferences.getMasterHexEncodedPublicKey(context) != null) {
|
} else if (isRequest && TextSecurePreferences.getMasterHexEncodedPublicKey(context) != null) {
|
||||||
Log.d("Loki", "Ignoring unexpected device link message (the device is a slave device).")
|
Log.d("Loki", "Ignoring unexpected device link message (the device is a slave device).")
|
||||||
return false
|
return false
|
||||||
} else if (isRequest && deviceLink.masterHexEncodedPublicKey != userPublicKey) {
|
} else if (isRequest && deviceLink.masterPublicKey != userPublicKey) {
|
||||||
Log.d("Loki", "Ignoring device linking message addressed to another user.")
|
Log.d("Loki", "Ignoring device linking message addressed to another user.")
|
||||||
return false
|
return false
|
||||||
} else if (isRequest && deviceLink.slaveHexEncodedPublicKey == userPublicKey) {
|
} else if (isRequest && deviceLink.slavePublicKey == userPublicKey) {
|
||||||
Log.d("Loki", "Ignoring device linking request message from self.")
|
Log.d("Loki", "Ignoring device linking request message from self.")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -193,9 +193,9 @@ object MultiDeviceProtocol {
|
|||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).clearDeviceLinks(userPublicKey)
|
DatabaseFactory.getLokiAPIDatabase(context).clearDeviceLinks(userPublicKey)
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).addDeviceLink(deviceLink)
|
DatabaseFactory.getLokiAPIDatabase(context).addDeviceLink(deviceLink)
|
||||||
TextSecurePreferences.setMasterHexEncodedPublicKey(context, deviceLink.masterHexEncodedPublicKey)
|
TextSecurePreferences.setMasterHexEncodedPublicKey(context, deviceLink.masterPublicKey)
|
||||||
TextSecurePreferences.setMultiDevice(context, true)
|
TextSecurePreferences.setMultiDevice(context, true)
|
||||||
LokiFileServerAPI.shared.addDeviceLink(deviceLink)
|
FileServerAPI.shared.addDeviceLink(deviceLink)
|
||||||
org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol.handleProfileUpdateIfNeeded(context, content)
|
org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol.handleProfileUpdateIfNeeded(context, content)
|
||||||
org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol.duplicate_handleProfileKey(context, content)
|
org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol.duplicate_handleProfileKey(context, content)
|
||||||
}
|
}
|
||||||
@ -210,19 +210,19 @@ object MultiDeviceProtocol {
|
|||||||
// Ignore the request if we don't know about the device link in question
|
// Ignore the request if we don't know about the device link in question
|
||||||
val masterDeviceLinks = DatabaseFactory.getLokiAPIDatabase(context).getDeviceLinks(masterDevicePublicKey)
|
val masterDeviceLinks = DatabaseFactory.getLokiAPIDatabase(context).getDeviceLinks(masterDevicePublicKey)
|
||||||
if (masterDeviceLinks.none {
|
if (masterDeviceLinks.none {
|
||||||
it.masterHexEncodedPublicKey == masterDevicePublicKey && it.slaveHexEncodedPublicKey == userPublicKey
|
it.masterPublicKey == masterDevicePublicKey && it.slavePublicKey == userPublicKey
|
||||||
}) {
|
}) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
LokiFileServerAPI.shared.getDeviceLinks(userPublicKey, true).success { slaveDeviceLinks ->
|
FileServerAPI.shared.getDeviceLinks(userPublicKey, true).success { slaveDeviceLinks ->
|
||||||
// Check that the device link IS present on the file server.
|
// Check that the device link IS present on the file server.
|
||||||
// Note that the device link as seen from the master device's perspective has been deleted at this point, but the
|
// Note that the device link as seen from the master device's perspective has been deleted at this point, but the
|
||||||
// device link as seen from the slave perspective hasn't.
|
// device link as seen from the slave perspective hasn't.
|
||||||
if (slaveDeviceLinks.any {
|
if (slaveDeviceLinks.any {
|
||||||
it.masterHexEncodedPublicKey == masterDevicePublicKey && it.slaveHexEncodedPublicKey == userPublicKey
|
it.masterPublicKey == masterDevicePublicKey && it.slavePublicKey == userPublicKey
|
||||||
}) {
|
}) {
|
||||||
for (slaveDeviceLink in slaveDeviceLinks) { // In theory there should only be one
|
for (slaveDeviceLink in slaveDeviceLinks) { // In theory there should only be one
|
||||||
LokiFileServerAPI.shared.removeDeviceLink(slaveDeviceLink) // Attempt to clean up on the file server
|
FileServerAPI.shared.removeDeviceLink(slaveDeviceLink) // Attempt to clean up on the file server
|
||||||
}
|
}
|
||||||
TextSecurePreferences.setWasUnlinked(context, true)
|
TextSecurePreferences.setWasUnlinked(context, true)
|
||||||
ApplicationContext.getInstance(context).clearData()
|
ApplicationContext.getInstance(context).clearData()
|
||||||
|
@ -44,12 +44,11 @@ class PushEphemeralMessageSendJob private constructor(parameters: Parameters, pr
|
|||||||
// Attach a pre key bundle if needed
|
// Attach a pre key bundle if needed
|
||||||
if (message.get("friendRequest", false)) {
|
if (message.get("friendRequest", false)) {
|
||||||
val bundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(recipient)
|
val bundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(recipient)
|
||||||
dataMessage.withPreKeyBundle(bundle).asFriendRequest(true)
|
dataMessage.withPreKeyBundle(bundle)
|
||||||
}
|
}
|
||||||
// Set flags if needed (these are mutually exclusive)
|
// Set flags if needed (these are mutually exclusive)
|
||||||
when {
|
when {
|
||||||
message.get("unpairingRequest", false) -> dataMessage.asUnlinkingRequest(true)
|
message.get("unpairingRequest", false) -> dataMessage.asDeviceUnlinkingRequest(true)
|
||||||
message.get("sessionRestore", false) -> dataMessage.asSessionRestorationRequest(true)
|
|
||||||
message.get("sessionRequest", false) -> dataMessage.asSessionRequest(true)
|
message.get("sessionRequest", false) -> dataMessage.asSessionRequest(true)
|
||||||
}
|
}
|
||||||
// Send the message
|
// Send the message
|
||||||
|
@ -56,7 +56,7 @@ class PushNullMessageSendJob private constructor(parameters: Parameters, private
|
|||||||
try {
|
try {
|
||||||
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess,
|
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess,
|
||||||
Date().time, serializedContentMessage, false, ttl, false,
|
Date().time, serializedContentMessage, false, ttl, false,
|
||||||
false, false, false, false)
|
false, false, false)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Loki", "Failed to send null message to: $publicKey due to error: $e.")
|
Log.d("Loki", "Failed to send null message to: $publicKey due to error: $e.")
|
||||||
throw e
|
throw e
|
||||||
|
@ -13,7 +13,7 @@ import org.thoughtcrime.securesms.loki.utilities.recipient
|
|||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
|
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.libsignal.loki.LokiSessionResetStatus
|
import org.whispersystems.libsignal.loki.SessionResetStatus
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent
|
import org.whispersystems.signalservice.api.messages.SignalServiceContent
|
||||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -93,7 +93,7 @@ object SessionManagementProtocol {
|
|||||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||||
Log.d("Loki", "Received a session reset request from: ${content.sender}; archiving the session.")
|
Log.d("Loki", "Received a session reset request from: ${content.sender}; archiving the session.")
|
||||||
sessionStore.archiveAllSessions(content.sender)
|
sessionStore.archiveAllSessions(content.sender)
|
||||||
lokiThreadDB.setSessionResetStatus(content.sender, LokiSessionResetStatus.REQUEST_RECEIVED)
|
lokiThreadDB.setSessionResetStatus(content.sender, SessionResetStatus.REQUEST_RECEIVED)
|
||||||
Log.d("Loki", "Sending an ephemeral message back to: ${content.sender}.")
|
Log.d("Loki", "Sending an ephemeral message back to: ${content.sender}.")
|
||||||
val ephemeralMessage = EphemeralMessage.create(content.sender)
|
val ephemeralMessage = EphemeralMessage.create(content.sender)
|
||||||
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(ephemeralMessage))
|
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(ephemeralMessage))
|
||||||
|
@ -22,7 +22,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceGroup
|
|||||||
import org.whispersystems.signalservice.api.messages.multidevice.ContactsMessage
|
import org.whispersystems.signalservice.api.messages.multidevice.ContactsMessage
|
||||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsInputStream
|
import org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsInputStream
|
||||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsInputStream
|
import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsInputStream
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiMessageFriendRequestStatus
|
import org.whispersystems.signalservice.loki.protocol.todo.LokiMessageFriendRequestStatus
|
||||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||||
@ -151,7 +151,7 @@ object SyncMessagesProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun handleOpenGroupSyncMessage(context: Context, content: SignalServiceContent, openGroups: List<LokiPublicChat>) {
|
fun handleOpenGroupSyncMessage(context: Context, content: SignalServiceContent, openGroups: List<PublicChat>) {
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||||
val allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey)
|
val allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey)
|
||||||
if (!allUserDevices.contains(content.sender)) { return }
|
if (!allUserDevices.contains(content.sender)) { return }
|
||||||
|
@ -66,7 +66,7 @@ class LokiRSSFeedPoller(private val context: Context, private val feed: LokiRSSF
|
|||||||
val id = feed.id.toByteArray()
|
val id = feed.id.toByteArray()
|
||||||
val x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.RSS_FEED, null, null, null, null)
|
val x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.RSS_FEED, null, null, null, null)
|
||||||
val x2 = SignalServiceDataMessage(timestamp, x1, null, body)
|
val x2 = SignalServiceDataMessage(timestamp, x1, null, body)
|
||||||
val x3 = SignalServiceContent(x2, "Loki", SignalServiceAddress.DEFAULT_DEVICE_ID, timestamp, false, false, false, false)
|
val x3 = SignalServiceContent(x2, "Loki", SignalServiceAddress.DEFAULT_DEVICE_ID, timestamp, false, false, false)
|
||||||
PushDecryptJob(context).handleTextMessage(x3, x2, Optional.absent(), Optional.absent())
|
PushDecryptJob(context).handleTextMessage(x3, x2, Optional.absent(), Optional.absent())
|
||||||
}
|
}
|
||||||
}.fail { exception ->
|
}.fail { exception ->
|
||||||
|
@ -47,7 +47,7 @@ object ContactUtilities {
|
|||||||
var isSlave = false
|
var isSlave = false
|
||||||
if (!recipient.isGroupRecipient) {
|
if (!recipient.isGroupRecipient) {
|
||||||
val deviceLinks = lokiAPIDatabase.getDeviceLinks(publicKey)
|
val deviceLinks = lokiAPIDatabase.getDeviceLinks(publicKey)
|
||||||
isSlave = deviceLinks.find { it.slaveHexEncodedPublicKey == publicKey } != null
|
isSlave = deviceLinks.find { it.slavePublicKey == publicKey } != null
|
||||||
}
|
}
|
||||||
result.add(Contact(recipient, isFriend, isSlave, isUserDevice))
|
result.add(Contact(recipient, isFriend, isSlave, isUserDevice))
|
||||||
}
|
}
|
||||||
|
@ -8,20 +8,20 @@ import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
|
|||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.groups.GroupManager
|
import org.thoughtcrime.securesms.groups.GroupManager
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||||
|
|
||||||
object OpenGroupUtilities {
|
object OpenGroupUtilities {
|
||||||
|
|
||||||
@JvmStatic fun addGroup(context: Context, url: String, channel: Long): Promise<LokiPublicChat, Exception> {
|
@JvmStatic fun addGroup(context: Context, url: String, channel: Long): Promise<PublicChat, Exception> {
|
||||||
// Check for an existing group
|
// Check for an existing group
|
||||||
val groupID = LokiPublicChat.getId(channel, url)
|
val groupID = PublicChat.getId(channel, url)
|
||||||
val threadID = GroupManager.getOpenGroupThreadID(groupID, context)
|
val threadID = GroupManager.getOpenGroupThreadID(groupID, context)
|
||||||
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
||||||
if (openGroup != null) { return Promise.of(openGroup) }
|
if (openGroup != null) { return Promise.of(openGroup) }
|
||||||
// Add the new group
|
// Add the new group
|
||||||
val application = ApplicationContext.getInstance(context)
|
val application = ApplicationContext.getInstance(context)
|
||||||
val displayName = TextSecurePreferences.getProfileName(context)
|
val displayName = TextSecurePreferences.getProfileName(context)
|
||||||
val lokiPublicChatAPI = application.lokiPublicChatAPI ?: throw Error("LokiPublicChatAPI is not initialized.")
|
val lokiPublicChatAPI = application.publicChatAPI ?: throw Error("LokiPublicChatAPI is not initialized.")
|
||||||
return application.lokiPublicChatManager.addChat(url, channel).then { group ->
|
return application.lokiPublicChatManager.addChat(url, channel).then { group ->
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastMessageServerID(channel, url)
|
DatabaseFactory.getLokiAPIDatabase(context).removeLastMessageServerID(channel, url)
|
||||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(channel, url)
|
DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(channel, url)
|
||||||
|
@ -9,7 +9,7 @@ import android.widget.LinearLayout
|
|||||||
import kotlinx.android.synthetic.main.view_mention_candidate.view.*
|
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.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI
|
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatAPI
|
||||||
import org.whispersystems.signalservice.loki.protocol.mentions.Mention
|
import org.whispersystems.signalservice.loki.protocol.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) {
|
||||||
@ -31,13 +31,13 @@ class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr:
|
|||||||
|
|
||||||
private fun update() {
|
private fun update() {
|
||||||
displayNameTextView.text = mentionCandidate.displayName
|
displayNameTextView.text = mentionCandidate.displayName
|
||||||
profilePictureView.hexEncodedPublicKey = mentionCandidate.hexEncodedPublicKey
|
profilePictureView.hexEncodedPublicKey = mentionCandidate.publicKey
|
||||||
profilePictureView.additionalHexEncodedPublicKey = null
|
profilePictureView.additionalHexEncodedPublicKey = null
|
||||||
profilePictureView.isRSSFeed = false
|
profilePictureView.isRSSFeed = false
|
||||||
profilePictureView.glide = glide!!
|
profilePictureView.glide = glide!!
|
||||||
profilePictureView.update()
|
profilePictureView.update()
|
||||||
if (publicChatServer != null && publicChatChannel != null) {
|
if (publicChatServer != null && publicChatChannel != null) {
|
||||||
val isUserModerator = LokiPublicChatAPI.isUserModerator(mentionCandidate.hexEncodedPublicKey, publicChatChannel!!, publicChatServer!!)
|
val isUserModerator = PublicChatAPI.isUserModerator(mentionCandidate.publicKey, publicChatChannel!!, publicChatServer!!)
|
||||||
moderatorIconImageView.visibility = if (isUserModerator) View.VISIBLE else View.GONE
|
moderatorIconImageView.visibility = if (isUserModerator) View.VISIBLE else View.GONE
|
||||||
} else {
|
} else {
|
||||||
moderatorIconImageView.visibility = View.GONE
|
moderatorIconImageView.visibility = View.GONE
|
||||||
|
@ -3,7 +3,7 @@ package org.thoughtcrime.securesms.mms;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI;
|
||||||
|
|
||||||
public class PushMediaConstraints extends MediaConstraints {
|
public class PushMediaConstraints extends MediaConstraints {
|
||||||
|
|
||||||
@ -22,26 +22,26 @@ public class PushMediaConstraints extends MediaConstraints {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getImageMaxSize(Context context) {
|
public int getImageMaxSize(Context context) {
|
||||||
return LokiFileServerAPI.Companion.getMaxFileSize();
|
return FileServerAPI.Companion.getMaxFileSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getGifMaxSize(Context context) {
|
public int getGifMaxSize(Context context) {
|
||||||
return LokiFileServerAPI.Companion.getMaxFileSize();
|
return FileServerAPI.Companion.getMaxFileSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getVideoMaxSize(Context context) {
|
public int getVideoMaxSize(Context context) {
|
||||||
return LokiFileServerAPI.Companion.getMaxFileSize();
|
return FileServerAPI.Companion.getMaxFileSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAudioMaxSize(Context context) {
|
public int getAudioMaxSize(Context context) {
|
||||||
return LokiFileServerAPI.Companion.getMaxFileSize();
|
return FileServerAPI.Companion.getMaxFileSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDocumentMaxSize(Context context) {
|
public int getDocumentMaxSize(Context context) {
|
||||||
return LokiFileServerAPI.Companion.getMaxFileSize();
|
return FileServerAPI.Companion.getMaxFileSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.push;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.SecurityEvent;
|
import org.thoughtcrime.securesms.crypto.SecurityEvent;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.FriendRequestProtocol;
|
|
||||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
@ -18,19 +17,4 @@ public class MessageSenderEventListener implements SignalServiceMessageSender.Ev
|
|||||||
public void onSecurityEvent(SignalServiceAddress textSecureAddress) {
|
public void onSecurityEvent(SignalServiceAddress textSecureAddress) {
|
||||||
SecurityEvent.broadcastSecurityUpdateEvent(context);
|
SecurityEvent.broadcastSecurityUpdateEvent(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFriendRequestSending(long messageID, long threadID) {
|
|
||||||
FriendRequestProtocol.setFriendRequestStatusToSendingIfNeeded(context, messageID, threadID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFriendRequestSent(long messageID, long threadID) {
|
|
||||||
FriendRequestProtocol.setFriendRequestStatusToSentIfNeeded(context, messageID, threadID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFriendRequestSendingFailed(long messageID, long threadID) {
|
|
||||||
FriendRequestProtocol.setFriendRequestStatusToFailedIfNeeded(context, messageID, threadID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user