mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-25 01:07:47 +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.SnodeAPI;
|
||||
import org.whispersystems.signalservice.loki.api.SwarmAPI;
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI;
|
||||
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.LokiP2PAPIDelegate;
|
||||
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.meta.SessionMetaProtocol;
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink;
|
||||
@ -156,7 +155,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
public MessageNotifier messageNotifier = null;
|
||||
public Poller lokiPoller = null;
|
||||
public LokiPublicChatManager lokiPublicChatManager = null;
|
||||
private LokiPublicChatAPI lokiPublicChatAPI = null;
|
||||
private PublicChatAPI publicChatAPI = null;
|
||||
public Broadcaster broadcaster = null;
|
||||
public SignalCommunicationModule communicationModule;
|
||||
|
||||
@ -189,7 +188,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
if (userPublicKey != null) {
|
||||
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||
FriendRequestProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
||||
SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||
SyncMessagesProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||
@ -201,7 +199,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
if (setUpStorageAPIIfNeeded()) {
|
||||
if (userPublicKey != null) {
|
||||
Set<DeviceLink> deviceLinks = DatabaseFactory.getLokiAPIDatabase(this).getDeviceLinks(userPublicKey);
|
||||
LokiFileServerAPI.shared.setDeviceLinks(deviceLinks);
|
||||
FileServerAPI.shared.setDeviceLinks(deviceLinks);
|
||||
}
|
||||
}
|
||||
resubmitProfilePictureIfNeeded();
|
||||
@ -284,15 +282,15 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
}
|
||||
|
||||
// Loki
|
||||
public @Nullable LokiPublicChatAPI getLokiPublicChatAPI() {
|
||||
if (lokiPublicChatAPI != null || !IdentityKeyUtil.hasIdentityKey(this)) { return lokiPublicChatAPI; }
|
||||
public @Nullable PublicChatAPI getPublicChatAPI() {
|
||||
if (publicChatAPI != null || !IdentityKeyUtil.hasIdentityKey(this)) { return publicChatAPI; }
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
if (userPublicKey== null) { return lokiPublicChatAPI; }
|
||||
if (userPublicKey== null) { return publicChatAPI; }
|
||||
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
||||
lokiPublicChatAPI = new LokiPublicChatAPI(userPublicKey, userPrivateKey, apiDB, userDB);
|
||||
return lokiPublicChatAPI;
|
||||
publicChatAPI = new PublicChatAPI(userPublicKey, userPrivateKey, apiDB, userDB);
|
||||
return publicChatAPI;
|
||||
}
|
||||
|
||||
private void initializeSecurityProvider() {
|
||||
@ -446,8 +444,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
super.attachBaseContext(DynamicLanguageContextWrapper.updateContext(base, TextSecurePreferences.getLanguage(base)));
|
||||
}
|
||||
|
||||
private static class ProviderInitializationException extends RuntimeException {
|
||||
}
|
||||
private static class ProviderInitializationException extends RuntimeException { }
|
||||
|
||||
// region Loki
|
||||
public boolean setUpStorageAPIIfNeeded() {
|
||||
@ -456,7 +453,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
boolean isDebugMode = BuildConfig.DEBUG;
|
||||
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
|
||||
LokiAPIDatabaseProtocol apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
||||
LokiFileServerAPI.Companion.configure(isDebugMode, userPublicKey, userPrivateKey, apiDB);
|
||||
FileServerAPI.Companion.configure(userPublicKey, userPrivateKey, apiDB);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -534,7 +531,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
try {
|
||||
File profilePicture = AvatarHelper.getAvatarFile(this, Address.fromSerialized(userPublicKey));
|
||||
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.setProfileAvatarId(this, new SecureRandom().nextInt());
|
||||
ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey);
|
||||
@ -548,9 +545,9 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
|
||||
public void updateOpenGroupProfilePicturesIfNeeded() {
|
||||
AsyncTask.execute(() -> {
|
||||
LokiPublicChatAPI publicChatAPI = null;
|
||||
PublicChatAPI publicChatAPI = null;
|
||||
try {
|
||||
publicChatAPI = getLokiPublicChatAPI();
|
||||
publicChatAPI = getPublicChatAPI();
|
||||
} catch (Exception e) {
|
||||
// Do nothing
|
||||
}
|
||||
@ -590,7 +587,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSessionRequest(@NotNull String publicKey) {
|
||||
public void sendSessionRequestIfNeeded(@NotNull String publicKey) {
|
||||
// It's never necessary to establish a session with self
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
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.util.StreamDetails;
|
||||
import org.whispersystems.signalservice.loki.api.LokiDotNetAPI;
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatAPI;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
@ -386,7 +386,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
||||
Context context = CreateProfileActivity.this;
|
||||
|
||||
TextSecurePreferences.setProfileName(context, name);
|
||||
LokiPublicChatAPI publicChatAPI = ApplicationContext.getInstance(context).getLokiPublicChatAPI();
|
||||
PublicChatAPI publicChatAPI = ApplicationContext.getInstance(context).getPublicChatAPI();
|
||||
if (publicChatAPI != null) {
|
||||
Set<String> servers = DatabaseFactory.getLokiThreadDatabase(context).getAllPublicChatServers();
|
||||
for (String server : servers) {
|
||||
@ -409,7 +409,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
||||
// Loki - Upload the profile photo here
|
||||
if (avatar != null) {
|
||||
Log.d("Loki", "Start uploading profile photo");
|
||||
LokiFileServerAPI storageAPI = LokiFileServerAPI.shared;
|
||||
FileServerAPI storageAPI = FileServerAPI.shared;
|
||||
LokiDotNetAPI.UploadResult result = storageAPI.uploadProfilePicture(storageAPI.getServer(), profileKey, avatar, () -> {
|
||||
TextSecurePreferences.setLastProfilePictureUpload(CreateProfileActivity.this, new Date().getTime());
|
||||
return Unit.INSTANCE;
|
||||
|
@ -31,7 +31,7 @@ import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||
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;
|
||||
|
||||
@ -197,7 +197,7 @@ public class QuoteView extends FrameLayout implements RecipientModifiedListener
|
||||
|
||||
long threadID = DatabaseFactory.getThreadDatabase(getContext()).getThreadIdFor(conversationRecipient);
|
||||
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()))) {
|
||||
quoteeDisplayName = TextSecurePreferences.getProfileName(getContext());
|
||||
} 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.VideoSlide;
|
||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
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.whispersystems.libsignal.InvalidMessageException;
|
||||
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.MentionsManager;
|
||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
|
||||
@ -465,9 +464,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
MentionManagerUtilities.INSTANCE.populateUserPublicKeyCacheIfNeeded(threadId, this);
|
||||
|
||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||
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();
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
@ -2172,7 +2171,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
try {
|
||||
int startIndex = result.indexOf("@" + mention.getDisplayName());
|
||||
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) {
|
||||
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);
|
||||
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")) {
|
||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId);
|
||||
if (publicChat != null) {
|
||||
Integer userCount = DatabaseFactory.getLokiAPIDatabase(this).getUserCount(publicChat.getChannel(), publicChat.getServer());
|
||||
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.task.ProgressDialogAsyncTask;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatAPI;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -399,7 +399,7 @@ public class ConversationFragment extends Fragment
|
||||
boolean isGroupChat = recipient.isGroupRecipient();
|
||||
|
||||
if (isGroupChat) {
|
||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||
boolean isPublicChat = (publicChat != null);
|
||||
int selectedMessageCount = messageRecords.size();
|
||||
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_reply).setVisible(selectedMessageCount == 1);
|
||||
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);
|
||||
menu.findItem(R.id.menu_context_delete_message).setVisible(isDeleteOptionVisible);
|
||||
} 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.setCancelable(true);
|
||||
|
||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(getContext()).getPublicChat(threadId);
|
||||
|
||||
builder.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
@ -518,7 +518,7 @@ public class ConversationFragment extends Fragment
|
||||
ArrayList<Long> ignoredMessages = new ArrayList<>();
|
||||
ArrayList<Long> failedMessages = new ArrayList<>();
|
||||
boolean isSentByUser = true;
|
||||
LokiPublicChatAPI publicChatAPI = ApplicationContext.getInstance(getContext()).getLokiPublicChatAPI();
|
||||
PublicChatAPI publicChatAPI = ApplicationContext.getInstance(getContext()).getPublicChatAPI();
|
||||
for (MessageRecord messageRecord : messageRecords) {
|
||||
isSentByUser = isSentByUser && messageRecord.isOutgoing();
|
||||
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.views.Stub;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat;
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatAPI;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@ -1001,9 +1001,9 @@ public class ConversationItem extends LinearLayout
|
||||
profilePictureView.setVisibility(VISIBLE);
|
||||
int visibility = View.GONE;
|
||||
|
||||
LokiPublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(messageRecord.getThreadId());
|
||||
PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(messageRecord.getThreadId());
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
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;
|
||||
|
||||
@ -545,7 +545,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
try (Cursor lokiPublicChatCursor = db.rawQuery("SELECT public_chat FROM loki_public_chat_database", null)) {
|
||||
while (lokiPublicChatCursor != null && lokiPublicChatCursor.moveToNext()) {
|
||||
String chatString = lokiPublicChatCursor.getString(0);
|
||||
LokiPublicChat publicChat = LokiPublicChat.fromJSON(chatString);
|
||||
PublicChat publicChat = PublicChat.fromJSON(chatString);
|
||||
if (publicChat != null) {
|
||||
byte[] groupId = publicChat.getId().getBytes();
|
||||
String oldId = GroupUtil.getEncodedId(groupId, false);
|
||||
|
@ -152,7 +152,6 @@ public class SignalCommunicationModule {
|
||||
Optional.fromNullable(IncomingMessageObserver.getUnidentifiedPipe()),
|
||||
Optional.of(new MessageSenderEventListener(context)),
|
||||
TextSecurePreferences.getLocalNumber(context),
|
||||
TextSecurePreferences.getMasterHexEncodedPublicKey(context),
|
||||
DatabaseFactory.getLokiAPIDatabase(context),
|
||||
DatabaseFactory.getLokiThreadDatabase(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.SignalServiceAttachmentPointer;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
|
||||
|
||||
import java.io.IOException;
|
||||
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.MultiDeviceProtocol;
|
||||
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.SessionMetaProtocol;
|
||||
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.MediaUtil;
|
||||
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.util.guava.Optional;
|
||||
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.shared.SharedContact;
|
||||
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.protocol.mentions.MentionsManager;
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus;
|
||||
@ -263,11 +262,11 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
|
||||
private void handleMessage(@NonNull SignalServiceEnvelope envelope, @NonNull Optional<Long> smsMessageId, boolean isPushNotification) {
|
||||
try {
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
SignalProtocolStore axolotlStore = new SignalProtocolStoreImpl(context);
|
||||
LokiSessionResetProtocol lokiSessionResetProtocol = new LokiSessionResetImplementation(context);
|
||||
SignalServiceAddress localAddress = new SignalServiceAddress(TextSecurePreferences.getLocalNumber(context));
|
||||
LokiServiceCipher cipher = new LokiServiceCipher(localAddress, axolotlStore, lokiSessionResetProtocol, UnidentifiedAccessUtil.getCertificateValidator());
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
SignalProtocolStore axolotlStore = new SignalProtocolStoreImpl(context);
|
||||
SessionResetProtocol sessionResetProtocol = new LokiSessionResetImplementation(context);
|
||||
SignalServiceAddress localAddress = new SignalServiceAddress(TextSecurePreferences.getLocalNumber(context));
|
||||
LokiServiceCipher cipher = new LokiServiceCipher(localAddress, axolotlStore, sessionResetProtocol, UnidentifiedAccessUtil.getCertificateValidator());
|
||||
|
||||
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();
|
||||
|
||||
// Loki - Handle unlinking request if needed
|
||||
if (message.isUnlinkingRequest()) {
|
||||
if (message.isDeviceUnlinkingRequest()) {
|
||||
MultiDeviceProtocol.handleUnlinkingRequestIfNeeded(context, content);
|
||||
} else {
|
||||
// Loki - Don't process session restoration requests any further
|
||||
if (message.isSessionRestorationRequest()) { return; }
|
||||
|
||||
// Loki - Handle friend request acceptance if needed
|
||||
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
|
||||
// ========
|
||||
if (content.isFriendRequest()) {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new PushNullMessageSendJob(content.getSender()));
|
||||
} else {
|
||||
Log.w(TAG, "Got unrecognized message...");
|
||||
}
|
||||
// if (content.isFriendRequest()) {
|
||||
// ApplicationContext.getInstance(context).getJobManager().add(new PushNullMessageSendJob(content.getSender()));
|
||||
// } else {
|
||||
// Log.w(TAG, "Got unrecognized message...");
|
||||
// }
|
||||
Recipient recipient = recipient(context, content.getSender());
|
||||
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context);
|
||||
@ -1432,7 +1428,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
} else {
|
||||
try {
|
||||
// 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);
|
||||
if (masterPublicKey == null) {
|
||||
masterPublicKey = publicKey;
|
||||
@ -1464,7 +1460,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
} else {
|
||||
try {
|
||||
// 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);
|
||||
if (masterPublicKey == null) {
|
||||
masterPublicKey = publicKey;
|
||||
|
@ -291,7 +291,6 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
.withPreviews(previews)
|
||||
.asExpirationUpdate(message.isExpirationUpdate())
|
||||
.withPreKeyBundle(preKeyBundle)
|
||||
.asFriendRequest(isLokiPreKeyBundleMessage)
|
||||
.build();
|
||||
|
||||
if (SessionMetaProtocol.shared.isNoteToSelf(address.getNumber())) {
|
||||
|
@ -36,7 +36,7 @@ public abstract class PushReceivedJob extends BaseJob {
|
||||
|
||||
if (envelope.isReceipt()) {
|
||||
handleReceipt(envelope);
|
||||
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage() || envelope.isUnidentifiedSender() || envelope.isFriendRequest()) {
|
||||
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage() || envelope.isUnidentifiedSender()) {
|
||||
handleMessage(envelope, isPushNotification);
|
||||
} else {
|
||||
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.Job;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
||||
@ -229,7 +228,6 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
.withExpiration((int)(message.getExpiresIn() / 1000))
|
||||
.withProfileKey(profileKey.orNull())
|
||||
.asEndSessionMessage(message.isEndSession())
|
||||
.asFriendRequest(isLokiPreKeyBundleMessage)
|
||||
.withPreKeyBundle(preKeyBundle)
|
||||
.build();
|
||||
|
||||
|
@ -40,10 +40,8 @@ import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetViewDelegat
|
||||
import org.thoughtcrime.securesms.loki.views.SeedReminderViewDelegate
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
||||
import org.whispersystems.signalservice.loki.protocol.friendrequests.FriendRequestProtocol
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
|
||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
@ -160,7 +158,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
val sessionResetImpl = LokiSessionResetImplementation(this)
|
||||
if (userPublicKey != null) {
|
||||
FriendRequestProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
||||
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
SyncMessagesProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
@ -175,7 +172,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
}.map {
|
||||
it.recipient.address.toPhoneString()
|
||||
}.toSet()
|
||||
LokiFileServerAPI.shared.getDeviceLinks(publicKeys)
|
||||
FileServerAPI.shared.getDeviceLinks(publicKeys)
|
||||
// TODO: Temporary hack to unbork existing clients
|
||||
val allContacts = DatabaseFactory.getRecipientDatabase(this).allAddresses.map {
|
||||
MultiDeviceProtocol.shared.getMasterDevice(it.serialize()) ?: it.serialize()
|
||||
@ -311,7 +308,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
val apiDatabase = DatabaseFactory.getLokiAPIDatabase(activity)
|
||||
apiDatabase.removeLastMessageServerID(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)
|
||||
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.ECKeyPair
|
||||
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.meta.SessionMetaProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
||||
@ -111,7 +110,6 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
||||
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
val sessionResetImpl = LokiSessionResetImplementation(this)
|
||||
FriendRequestProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
||||
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol.configureIfNeeded(apiDB)
|
||||
@ -124,13 +122,13 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
||||
linkDeviceDialog.show(supportFragmentManager, "Link Device Dialog")
|
||||
AsyncTask.execute {
|
||||
retryIfNeeded(8) {
|
||||
MultiDeviceProtocol.sendDeviceLinkMessage(this@LandingActivity, deviceLink.masterHexEncodedPublicKey, deviceLink)
|
||||
MultiDeviceProtocol.sendDeviceLinkMessage(this@LandingActivity, deviceLink.masterPublicKey, deviceLink)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
||||
TextSecurePreferences.setMasterHexEncodedPublicKey(this, deviceLink.masterHexEncodedPublicKey)
|
||||
TextSecurePreferences.setMasterHexEncodedPublicKey(this, deviceLink.masterPublicKey)
|
||||
val intent = Intent(this, HomeActivity::class.java)
|
||||
show(intent)
|
||||
finish()
|
||||
|
@ -26,7 +26,7 @@ import org.thoughtcrime.securesms.loki.utilities.recipient
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
||||
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 kotlin.concurrent.schedule
|
||||
|
||||
@ -126,30 +126,30 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
val apiDB = DatabaseFactory.getLokiAPIDatabase(this)
|
||||
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) {
|
||||
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)
|
||||
deviceLinks.forEach { deviceLink ->
|
||||
// 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
|
||||
val unlinkingRequest = SignalServiceDataMessage.newBuilder()
|
||||
.withTimestamp(System.currentTimeMillis())
|
||||
.asUnlinkingRequest(true)
|
||||
.asDeviceUnlinkingRequest(true)
|
||||
val messageSender = ApplicationContext.getInstance(this@LinkedDevicesActivity).communicationModule.provideSignalMessageSender()
|
||||
val address = SignalServiceAddress(deviceLink.slaveHexEncodedPublicKey)
|
||||
val address = SignalServiceAddress(deviceLink.slavePublicKey)
|
||||
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
|
||||
} catch (e: Exception) {
|
||||
Log.d("Loki", "Failed to send unlinking request due to error: $e.")
|
||||
throw e
|
||||
}
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey)
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slavePublicKey)
|
||||
val sessionStore = TextSecureSessionStore(this@LinkedDevicesActivity)
|
||||
sessionStore.deleteAllSessions(deviceLink.slaveHexEncodedPublicKey)
|
||||
sessionStore.deleteAllSessions(deviceLink.slavePublicKey)
|
||||
}
|
||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||
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.whispersystems.signalservice.api.crypto.ProfileCipher
|
||||
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.File
|
||||
import java.security.SecureRandom
|
||||
@ -151,7 +151,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
val promises = mutableListOf<Promise<*, Exception>>()
|
||||
val displayName = displayNameToBeUploaded
|
||||
if (displayName != null) {
|
||||
val publicChatAPI = ApplicationContext.getInstance(this).lokiPublicChatAPI
|
||||
val publicChatAPI = ApplicationContext.getInstance(this).publicChatAPI
|
||||
if (publicChatAPI != null) {
|
||||
val servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers()
|
||||
promises.addAll(servers.map { publicChatAPI.setDisplayName(displayName, it) })
|
||||
@ -162,7 +162,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
val encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this)
|
||||
val profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(encodedProfileKey)
|
||||
if (isUpdatingProfilePicture && profilePicture != null) {
|
||||
val storageAPI = LokiFileServerAPI.shared
|
||||
val storageAPI = FileServerAPI.shared
|
||||
val deferred = deferred<Unit, Exception>()
|
||||
AsyncTask.execute {
|
||||
val stream = StreamDetails(ByteArrayInputStream(profilePicture), "image/jpeg", profilePicture.size.toLong())
|
||||
|
@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit
|
||||
class BackgroundPollWorker : PersistentAlarmManagerListener() {
|
||||
|
||||
companion object {
|
||||
private val pollInterval = TimeUnit.MINUTES.toMillis(15)
|
||||
private val pollInterval = TimeUnit.MINUTES.toMillis(30)
|
||||
|
||||
@JvmStatic
|
||||
fun schedule(context: Context) {
|
||||
|
@ -12,10 +12,10 @@ import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
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) {
|
||||
private var chats = mutableMapOf<Long, LokiPublicChat>()
|
||||
private var chats = mutableMapOf<Long, PublicChat>()
|
||||
private val pollers = mutableMapOf<Long, LokiPublicChatPoller>()
|
||||
private val observers = mutableMapOf<Long, ContentObserver>()
|
||||
private var isPolling = false
|
||||
@ -55,8 +55,8 @@ class LokiPublicChatManager(private val context: Context) {
|
||||
isPolling = false
|
||||
}
|
||||
|
||||
public fun addChat(server: String, channel: Long): Promise<LokiPublicChat, Exception> {
|
||||
val groupChatAPI = ApplicationContext.getInstance(context).lokiPublicChatAPI ?: return Promise.ofFail(IllegalStateException("LokiPublicChatAPI is not set!"))
|
||||
public fun addChat(server: String, channel: Long): Promise<PublicChat, Exception> {
|
||||
val groupChatAPI = ApplicationContext.getInstance(context).publicChatAPI ?: return Promise.ofFail(IllegalStateException("LokiPublicChatAPI is not set!"))
|
||||
return groupChatAPI.getAuthToken(server).bind {
|
||||
groupChatAPI.getChannelInfo(channel, server)
|
||||
}.map {
|
||||
@ -64,8 +64,8 @@ class LokiPublicChatManager(private val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
public fun addChat(server: String, channel: Long, name: String): LokiPublicChat {
|
||||
val chat = LokiPublicChat(channel, server, name, true)
|
||||
public fun addChat(server: String, channel: Long, name: String): PublicChat {
|
||||
val chat = PublicChat(channel, server, name, true)
|
||||
var threadID = GroupManager.getOpenGroupThreadID(chat.id, context)
|
||||
// Create the group if we don't have one
|
||||
if (threadID < 0) {
|
||||
@ -76,7 +76,7 @@ class LokiPublicChatManager(private val context: Context) {
|
||||
// Set our name on the server
|
||||
val displayName = TextSecurePreferences.getProfileName(context)
|
||||
if (!TextUtils.isEmpty(displayName)) {
|
||||
ApplicationContext.getInstance(context).lokiPublicChatAPI?.setDisplayName(displayName, server)
|
||||
ApplicationContext.getInstance(context).publicChatAPI?.setDisplayName(displayName, server)
|
||||
}
|
||||
// Start polling
|
||||
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.multidevice.SentTranscriptMessage
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatMessage
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatAPI
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChatMessage
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
import java.security.MessageDigest
|
||||
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 var hasStarted = 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 var displayNameUpdatees = setOf<String>()
|
||||
|
||||
private val api: LokiPublicChatAPI
|
||||
private val api: PublicChatAPI
|
||||
get() = {
|
||||
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
||||
val lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(context)
|
||||
val lokiUserDatabase = DatabaseFactory.getLokiUserDatabase(context)
|
||||
LokiPublicChatAPI(userHexEncodedPublicKey, userPrivateKey, lokiAPIDatabase, lokiUserDatabase)
|
||||
PublicChatAPI(userHexEncodedPublicKey, userPrivateKey, lokiAPIDatabase, lokiUserDatabase)
|
||||
}()
|
||||
// endregion
|
||||
|
||||
@ -112,16 +112,16 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
||||
// endregion
|
||||
|
||||
// region Polling
|
||||
private fun getDataMessage(message: LokiPublicChatMessage): SignalServiceDataMessage {
|
||||
private fun getDataMessage(message: PublicChatMessage): SignalServiceDataMessage {
|
||||
val id = group.id.toByteArray()
|
||||
val serviceGroup = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.PUBLIC_CHAT, null, null, null, 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 {
|
||||
null
|
||||
}
|
||||
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(
|
||||
attachment.serverID,
|
||||
attachment.contentType,
|
||||
@ -135,7 +135,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
||||
Optional.fromNullable(attachment.caption),
|
||||
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>()
|
||||
if (linkPreview != null) {
|
||||
val attachment = SignalServiceAttachmentPointer(
|
||||
@ -157,16 +157,16 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
||||
}
|
||||
|
||||
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
|
||||
val masterHexEncodedPublicKey = MultiDeviceProtocol.shared.getMasterDevice(message.hexEncodedPublicKey)
|
||||
val masterHexEncodedPublicKey = MultiDeviceProtocol.shared.getMasterDevice(message.publicKey)
|
||||
if (masterHexEncodedPublicKey == null) {
|
||||
val senderDisplayName = "${message.displayName} (...${message.hexEncodedPublicKey.takeLast(8)})"
|
||||
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.hexEncodedPublicKey, senderDisplayName)
|
||||
val senderDisplayName = "${message.displayName} (...${message.publicKey.takeLast(8)})"
|
||||
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.publicKey, senderDisplayName)
|
||||
}
|
||||
val senderHexEncodedPublicKey = masterHexEncodedPublicKey ?: message.hexEncodedPublicKey
|
||||
val senderHexEncodedPublicKey = masterHexEncodedPublicKey ?: message.publicKey
|
||||
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) {
|
||||
PushDecryptJob(context).handleMediaMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
|
||||
} 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 isDuplicate = DatabaseFactory.getLokiMessageDatabase(context).getMessageID(messageServerID) != null
|
||||
if (isDuplicate) { return }
|
||||
@ -206,7 +206,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
||||
PushDecryptJob(context).handleSynchronizeSentTextMessage(transcript)
|
||||
}
|
||||
// If we got a message from our master device then make sure our mapping stays in sync
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(message.hexEncodedPublicKey), false)
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(message.publicKey), false)
|
||||
if (recipient.isUserMasterDevice && message.profilePicture != null) {
|
||||
val profileKey = message.profilePicture!!.profileKey
|
||||
val url = message.profilePicture!!.url
|
||||
@ -222,15 +222,15 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
||||
var uniqueDevices = setOf<String>()
|
||||
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
||||
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
|
||||
api.getMessages(group.channel, group.server).bind(LokiPublicChatAPI.sharedContext) { messages ->
|
||||
api.getMessages(group.channel, group.server).bind(PublicChatAPI.sharedContext) { messages ->
|
||||
if (messages.isNotEmpty()) {
|
||||
// We need to fetch the device mapping for any devices we don't have
|
||||
uniqueDevices = messages.map { it.hexEncodedPublicKey }.toSet()
|
||||
val devicesToUpdate = uniqueDevices.filter { !userDevices.contains(it) && LokiFileServerAPI.shared.hasDeviceLinkCacheExpired(hexEncodedPublicKey = it) }
|
||||
uniqueDevices = messages.map { it.publicKey }.toSet()
|
||||
val devicesToUpdate = uniqueDevices.filter { !userDevices.contains(it) && FileServerAPI.shared.hasDeviceLinkCacheExpired(publicKey = it) }
|
||||
if (devicesToUpdate.isNotEmpty()) {
|
||||
return@bind LokiFileServerAPI.shared.getDeviceLinks(devicesToUpdate.toSet()).then { messages }
|
||||
return@bind FileServerAPI.shared.getDeviceLinks(devicesToUpdate.toSet()).then { messages }
|
||||
}
|
||||
}
|
||||
Promise.of(messages)
|
||||
@ -244,7 +244,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
|
||||
}.successBackground { messages ->
|
||||
// Process messages in the background
|
||||
messages.forEach { message ->
|
||||
if (userDevices.contains(message.hexEncodedPublicKey)) {
|
||||
if (userDevices.contains(message.publicKey)) {
|
||||
processOutgoingMessage(message)
|
||||
} else {
|
||||
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);"
|
||||
// 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"
|
||||
@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
|
||||
private val lastMessageHashValueCache = "loki_api_last_message_hash_value_cache"
|
||||
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);"
|
||||
// Device link cache
|
||||
private val deviceLinkCache = "loki_pairing_authorisation_cache"
|
||||
private val masterHexEncodedPublicKey = "primary_device"
|
||||
private val slaveHexEncodedPublicKey = "secondary_device"
|
||||
private val masterPublicKey = "primary_device"
|
||||
private val slavePublicKey = "secondary_device"
|
||||
private val requestSignature = "request_signature"
|
||||
private val authorizationSignature = "grant_signature"
|
||||
@JvmStatic val createDeviceLinkCacheCommand = "CREATE TABLE $deviceLinkCache ($masterHexEncodedPublicKey TEXT, $slaveHexEncodedPublicKey TEXT, " +
|
||||
"$requestSignature TEXT NULLABLE DEFAULT NULL, $authorizationSignature TEXT NULLABLE DEFAULT NULL, PRIMARY KEY ($masterHexEncodedPublicKey, $slaveHexEncodedPublicKey));"
|
||||
@JvmStatic val createDeviceLinkCacheCommand = "CREATE TABLE $deviceLinkCache ($masterPublicKey TEXT, $slavePublicKey TEXT, " +
|
||||
"$requestSignature TEXT NULLABLE DEFAULT NULL, $authorizationSignature TEXT NULLABLE DEFAULT NULL, PRIMARY KEY ($masterPublicKey, $slavePublicKey));"
|
||||
// User count cache
|
||||
private val userCountCache = "loki_user_count_cache"
|
||||
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);"
|
||||
// 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"
|
||||
@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> {
|
||||
@ -161,9 +161,9 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
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
|
||||
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))
|
||||
swarmAsString.split(", ").mapNotNull { targetAsString ->
|
||||
val components = targetAsString.split("-")
|
||||
@ -176,7 +176,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
}?.toSet()
|
||||
}
|
||||
|
||||
override fun setSwarm(hexEncodedPublicKey: String, newValue: Set<Snode>) {
|
||||
override fun setSwarm(publicKey: String, newValue: Set<Snode>) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val swarmAsString = newValue.joinToString(", ") { target ->
|
||||
var string = "${target.address}-${target.port}"
|
||||
@ -186,21 +186,21 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
}
|
||||
string
|
||||
}
|
||||
val row = wrap(mapOf(Companion.hexEncodedPublicKey to hexEncodedPublicKey, swarm to swarmAsString))
|
||||
database.insertOrUpdate(swarmCache, row, "${Companion.hexEncodedPublicKey} = ?", wrap(hexEncodedPublicKey))
|
||||
val row = wrap(mapOf(Companion.swarmPublicKey to publicKey, swarm to swarmAsString))
|
||||
database.insertOrUpdate(swarmCache, row, "${Companion.swarmPublicKey} = ?", wrap(publicKey))
|
||||
}
|
||||
|
||||
override fun getLastMessageHashValue(target: Snode): String? {
|
||||
override fun getLastMessageHashValue(snode: Snode): String? {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
override fun setLastMessageHashValue(target: Snode, newValue: String) {
|
||||
override fun setLastMessageHashValue(snode: Snode, newValue: String) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val row = wrap(mapOf(Companion.target to target.address, lastMessageHashValue to newValue))
|
||||
database.insertOrUpdate(lastMessageHashValueCache, row, "${Companion.target} = ?", wrap(target.address))
|
||||
val row = wrap(mapOf(Companion.target to snode.address, lastMessageHashValue to newValue))
|
||||
database.insertOrUpdate(lastMessageHashValueCache, row, "${Companion.target} = ?", wrap(snode.address))
|
||||
}
|
||||
|
||||
override fun getReceivedMessageHashValues(): Set<String>? {
|
||||
@ -277,35 +277,35 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
database.delete(lastDeletionServerIDCache,"$lastDeletionServerIDCacheIndex = ?", wrap(index))
|
||||
}
|
||||
|
||||
override fun getDeviceLinks(hexEncodedPublicKey: String): Set<DeviceLink> {
|
||||
override fun getDeviceLinks(publicKey: String): Set<DeviceLink> {
|
||||
val database = databaseHelper.readableDatabase
|
||||
return database.getAll(deviceLinkCache, "$masterHexEncodedPublicKey = ? OR $slaveHexEncodedPublicKey = ?", arrayOf( hexEncodedPublicKey, hexEncodedPublicKey )) { cursor ->
|
||||
val masterHexEncodedPublicKey = cursor.getString(masterHexEncodedPublicKey)
|
||||
val slaveHexEncodedPublicKey = cursor.getString(slaveHexEncodedPublicKey)
|
||||
return database.getAll(deviceLinkCache, "$masterPublicKey = ? OR $slavePublicKey = ?", arrayOf( publicKey, publicKey )) { cursor ->
|
||||
val masterHexEncodedPublicKey = cursor.getString(masterPublicKey)
|
||||
val slaveHexEncodedPublicKey = cursor.getString(slavePublicKey)
|
||||
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)
|
||||
DeviceLink(masterHexEncodedPublicKey, slaveHexEncodedPublicKey, requestSignature, authorizationSignature)
|
||||
}.toSet()
|
||||
}
|
||||
|
||||
override fun clearDeviceLinks(hexEncodedPublicKey: String) {
|
||||
override fun clearDeviceLinks(publicKey: String) {
|
||||
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) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val values = ContentValues()
|
||||
values.put(masterHexEncodedPublicKey, deviceLink.masterHexEncodedPublicKey)
|
||||
values.put(slaveHexEncodedPublicKey, deviceLink.slaveHexEncodedPublicKey)
|
||||
values.put(masterPublicKey, deviceLink.masterPublicKey)
|
||||
values.put(slavePublicKey, deviceLink.slavePublicKey)
|
||||
if (deviceLink.requestSignature != null) { values.put(requestSignature, Base64.encodeBytes(deviceLink.requestSignature)) }
|
||||
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) {
|
||||
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? {
|
||||
@ -332,8 +332,8 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
|
||||
override fun setSessionRequestTimestamp(publicKey: String, timestamp: Long) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val row = wrap(mapOf(LokiAPIDatabase.publicKey to publicKey, LokiAPIDatabase.timestamp to timestamp.toString()))
|
||||
database.insertOrUpdate(sessionRequestTimestampCache, row, "${LokiAPIDatabase.publicKey} = ?", wrap(publicKey))
|
||||
val row = wrap(mapOf(LokiAPIDatabase.sessionRequestPublicKey to publicKey, LokiAPIDatabase.timestamp to timestamp.toString()))
|
||||
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 {
|
||||
|
||||
companion object {
|
||||
private val messageFriendRequestTableName = "loki_message_friend_request_database"
|
||||
private val messageThreadMappingTableName = "loki_message_thread_mapping_database"
|
||||
private val errorMessageTableName = "loki_error_message_database"
|
||||
private val messageFriendRequestTable = "loki_message_friend_request_database"
|
||||
private val messageThreadMappingTable = "loki_message_thread_mapping_database"
|
||||
private val errorMessageTable = "loki_error_message_database"
|
||||
private val messageID = "message_id"
|
||||
private val serverID = "server_id"
|
||||
private val friendRequestStatus = "friend_request_status"
|
||||
private val threadID = "thread_id"
|
||||
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 createMessageToThreadMappingTableCommand = "CREATE TABLE IF NOT EXISTS $messageThreadMappingTableName ($messageID INTEGER PRIMARY KEY, $threadID INTEGER);"
|
||||
@JvmStatic val createErrorMessageTableCommand = "CREATE TABLE IF NOT EXISTS $errorMessageTableName ($messageID INTEGER PRIMARY KEY, $errorMessage STRING);"
|
||||
@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 $messageThreadMappingTable ($messageID INTEGER PRIMARY KEY, $threadID INTEGER);"
|
||||
@JvmStatic val createErrorMessageTableCommand = "CREATE TABLE IF NOT EXISTS $errorMessageTable ($messageID INTEGER PRIMARY KEY, $errorMessage STRING);"
|
||||
}
|
||||
|
||||
override fun getQuoteServerID(quoteID: Long, quoteeHexEncodedPublicKey: String): Long? {
|
||||
val message = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(quoteID, Address.fromSerialized(quoteeHexEncodedPublicKey))
|
||||
override fun getQuoteServerID(quoteID: Long, quoteePublicKey: String): Long? {
|
||||
val message = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(quoteID, Address.fromSerialized(quoteePublicKey))
|
||||
return if (message != null) getServerID(message.getId()) else null
|
||||
}
|
||||
|
||||
fun getServerID(messageID: Long): Long? {
|
||||
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)
|
||||
}?.toLong()
|
||||
}
|
||||
|
||||
fun getMessageID(serverID: Long): Long? {
|
||||
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)
|
||||
}?.toLong()
|
||||
}
|
||||
@ -53,12 +53,12 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.messageID, messageID)
|
||||
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 {
|
||||
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)
|
||||
}?.toLong() ?: -1L
|
||||
}
|
||||
@ -68,12 +68,12 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.messageID, messageID)
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
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 contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.messageID, messageID)
|
||||
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)
|
||||
notifyConversationListeners(threadID)
|
||||
}
|
||||
@ -99,7 +99,7 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
|
||||
fun getErrorMessage(messageID: Long): String? {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -109,6 +109,6 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.messageID, messageID)
|
||||
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 {
|
||||
|
||||
companion object {
|
||||
private val tableName = "loki_pre_key_bundle_database"
|
||||
private val hexEncodedPublicKey = "public_key"
|
||||
private val table = "loki_pre_key_bundle_database"
|
||||
private val publicKey = "public_key"
|
||||
private val preKeyID = "pre_key_id"
|
||||
private val preKeyPublic = "pre_key_public"
|
||||
private val signedPreKeyID = "signed_pre_key_id"
|
||||
@ -36,16 +36,16 @@ class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) :
|
||||
private val identityKey = "identity_key"
|
||||
private val deviceID = "device_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," +
|
||||
"$signedPreKeySignature TEXT," + "$identityKey TEXT NOT NULL," + "$deviceID INTEGER," + "$registrationID INTEGER" + ");"
|
||||
}
|
||||
|
||||
fun generatePreKeyBundle(hexEncodedPublicKey: String): PreKeyBundle? {
|
||||
fun generatePreKeyBundle(publicKey: String): PreKeyBundle? {
|
||||
var failureCount = 0
|
||||
while (failureCount < 3) {
|
||||
try {
|
||||
val preKey = generatePreKeyBundle(hexEncodedPublicKey, failureCount > 0) ?: return null
|
||||
val preKey = generatePreKeyBundle(publicKey, failureCount > 0) ?: return null
|
||||
// Verify the bundle is correct
|
||||
if (!Curve.verifySignature(preKey.identityKey.publicKey, preKey.signedPreKey.serialize(), preKey.signedPreKeySignature)) {
|
||||
throw InvalidKeyException()
|
||||
@ -55,19 +55,19 @@ class LokiPreKeyBundleDatabase(context: Context, helper: SQLCipherOpenHelper) :
|
||||
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
|
||||
}
|
||||
|
||||
private fun generatePreKeyBundle(hexEncodedPublicKey: String, forceClean: Boolean): PreKeyBundle? {
|
||||
if (hexEncodedPublicKey.isEmpty()) return null
|
||||
private fun generatePreKeyBundle(publicKey: String, forceClean: Boolean): PreKeyBundle? {
|
||||
if (publicKey.isEmpty()) return null
|
||||
var registrationID = TextSecurePreferences.getLocalRegistrationId(context)
|
||||
if (registrationID == 0) {
|
||||
registrationID = KeyHelper.generateRegistrationId(false)
|
||||
TextSecurePreferences.setLocalRegistrationId(context, registrationID)
|
||||
}
|
||||
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)
|
||||
if (!forceClean && TextSecurePreferences.isSignedPreKeyRegistered(context)) {
|
||||
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)
|
||||
}
|
||||
|
||||
override fun getPreKeyBundle(hexEncodedPublicKey: String): PreKeyBundle? {
|
||||
override fun getPreKeyBundle(publicKey: String): PreKeyBundle? {
|
||||
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 deviceID = cursor.getInt(deviceID)
|
||||
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 values = ContentValues(9)
|
||||
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(signedPreKeySignature, Base64.encodeBytes(preKeyBundle.signedPreKeySignature))
|
||||
values.put(identityKey, Base64.encodeBytes(preKeyBundle.identityKey.serialize()))
|
||||
values.put(Companion.hexEncodedPublicKey, hexEncodedPublicKey)
|
||||
database.insertOrUpdate(tableName, values, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey ))
|
||||
values.put(Companion.publicKey, publicKey)
|
||||
database.insertOrUpdate(table, values, "${Companion.publicKey} = ?", arrayOf( publicKey ))
|
||||
}
|
||||
|
||||
override fun removePreKeyBundle(hexEncodedPublicKey: String) {
|
||||
override fun removePreKeyBundle(publicKey: String) {
|
||||
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
|
||||
var cursor: Cursor? = null
|
||||
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
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
|
@ -14,38 +14,38 @@ import org.whispersystems.signalservice.loki.database.LokiPreKeyRecordDatabasePr
|
||||
class LokiPreKeyRecordDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiPreKeyRecordDatabaseProtocol {
|
||||
|
||||
companion object {
|
||||
private val tableName = "loki_pre_key_record_database"
|
||||
private val hexEncodedPublicKey = "public_key"
|
||||
private val table = "loki_pre_key_record_database"
|
||||
private val publicKey = "public_key"
|
||||
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
|
||||
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
|
||||
return database.get(tableName, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey )) { cursor ->
|
||||
return database.get(table, "${Companion.publicKey} = ?", arrayOf( publicKey )) { cursor ->
|
||||
val preKeyID = cursor.getInt(preKeyID)
|
||||
PreKeyUtil.loadPreKey(context, preKeyID)
|
||||
}
|
||||
}
|
||||
|
||||
fun getOrCreatePreKeyRecord(hexEncodedPublicKey: String): PreKeyRecord {
|
||||
return getPreKeyRecord(hexEncodedPublicKey) ?: generateAndStorePreKeyRecord(hexEncodedPublicKey)
|
||||
fun getOrCreatePreKeyRecord(publicKey: String): PreKeyRecord {
|
||||
return getPreKeyRecord(publicKey) ?: generateAndStorePreKeyRecord(publicKey)
|
||||
}
|
||||
|
||||
private fun generateAndStorePreKeyRecord(hexEncodedPublicKey: String): PreKeyRecord {
|
||||
private fun generateAndStorePreKeyRecord(publicKey: String): PreKeyRecord {
|
||||
val records = PreKeyUtil.generatePreKeyRecords(context, 1)
|
||||
PreKeyUtil.storePreKeyRecords(context, records)
|
||||
val record = records.first()
|
||||
val database = databaseHelper.writableDatabase
|
||||
val values = ContentValues(2)
|
||||
values.put(Companion.hexEncodedPublicKey, hexEncodedPublicKey)
|
||||
values.put(Companion.publicKey, publicKey)
|
||||
values.put(preKeyID, record.id)
|
||||
database.insertOrUpdate(tableName, values, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey ))
|
||||
database.insertOrUpdate(table, values, "${Companion.publicKey} = ?", arrayOf( publicKey ))
|
||||
return record
|
||||
}
|
||||
}
|
@ -11,9 +11,9 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||
import org.thoughtcrime.securesms.loki.utilities.*
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
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.loki.api.opengroups.LokiPublicChat
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||
import org.whispersystems.signalservice.loki.database.LokiThreadDatabaseProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
|
||||
@ -22,16 +22,16 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
||||
var delegate: LokiThreadDatabaseDelegate? = null
|
||||
|
||||
companion object {
|
||||
private val friendRequestTableName = "loki_thread_friend_request_database"
|
||||
private val sessionResetTableName = "loki_thread_session_reset_database"
|
||||
val publicChatTableName = "loki_public_chat_database"
|
||||
private val friendRequestTable = "loki_thread_friend_request_database"
|
||||
private val sessionResetTable = "loki_thread_session_reset_database"
|
||||
val publicChatTable = "loki_public_chat_database"
|
||||
val threadID = "thread_id"
|
||||
private val friendRequestStatus = "friend_request_status"
|
||||
private val sessionResetStatus = "session_reset_status"
|
||||
val publicChat = "public_chat"
|
||||
@JvmStatic val createFriendRequestTableCommand = "CREATE TABLE $friendRequestTableName ($threadID INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);"
|
||||
@JvmStatic val createSessionResetTableCommand = "CREATE TABLE $sessionResetTableName ($threadID INTEGER PRIMARY KEY, $sessionResetStatus INTEGER DEFAULT 0);"
|
||||
@JvmStatic val createPublicChatTableCommand = "CREATE TABLE $publicChatTableName ($threadID INTEGER PRIMARY KEY, $publicChat TEXT);"
|
||||
@JvmStatic val createFriendRequestTableCommand = "CREATE TABLE $friendRequestTable ($threadID INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);"
|
||||
@JvmStatic val createSessionResetTableCommand = "CREATE TABLE $sessionResetTable ($threadID INTEGER PRIMARY KEY, $sessionResetStatus INTEGER DEFAULT 0);"
|
||||
@JvmStatic val createPublicChatTableCommand = "CREATE TABLE $publicChatTable ($threadID INTEGER PRIMARY KEY, $publicChat TEXT);"
|
||||
}
|
||||
|
||||
override fun getThreadID(hexEncodedPublicKey: String): Long {
|
||||
@ -49,7 +49,7 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
||||
val recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID)
|
||||
if (recipient != null && recipient.isGroupRecipient) { return LokiThreadFriendRequestStatus.FRIENDS; }
|
||||
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)
|
||||
}
|
||||
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 }
|
||||
Log.d("Loki", "Setting FR status for thread with ID $threadID to $friendRequestStatus.")
|
||||
val database = databaseHelper.writableDatabase
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.threadID, threadID)
|
||||
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()
|
||||
notifyConversationListeners(threadID)
|
||||
delegate?.handleThreadFriendRequestStatusChanged(threadID)
|
||||
}
|
||||
|
||||
fun hasPendingFriendRequest(threadID: Long): Boolean {
|
||||
val friendRequestStatus = getFriendRequestStatus(threadID)
|
||||
return friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENDING || friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT
|
||||
|| friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_RECEIVED
|
||||
}
|
||||
|
||||
fun getSessionResetStatus(hexEncodedPublicKey: String): LokiSessionResetStatus {
|
||||
fun getSessionResetStatus(hexEncodedPublicKey: String): SessionResetStatus {
|
||||
val threadID = getThreadID(hexEncodedPublicKey)
|
||||
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)
|
||||
}
|
||||
return if (result != null) {
|
||||
LokiSessionResetStatus.values().first { it.rawValue == result }
|
||||
SessionResetStatus.values().first { it.rawValue == result }
|
||||
} else {
|
||||
LokiSessionResetStatus.NONE
|
||||
SessionResetStatus.NONE
|
||||
}
|
||||
}
|
||||
|
||||
fun setSessionResetStatus(hexEncodedPublicKey: String, sessionResetStatus: LokiSessionResetStatus) {
|
||||
fun setSessionResetStatus(hexEncodedPublicKey: String, sessionResetStatus: SessionResetStatus) {
|
||||
val threadID = getThreadID(hexEncodedPublicKey)
|
||||
val database = databaseHelper.writableDatabase
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.threadID, threadID)
|
||||
contentValues.put(Companion.sessionResetStatus, sessionResetStatus.rawValue)
|
||||
database.insertOrUpdate(sessionResetTableName, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
||||
database.insertOrUpdate(sessionResetTable, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
||||
notifyConversationListListeners()
|
||||
notifyConversationListeners(threadID)
|
||||
}
|
||||
|
||||
fun getAllPublicChats(): Map<Long, LokiPublicChat> {
|
||||
fun getAllPublicChats(): Map<Long, PublicChat> {
|
||||
val database = databaseHelper.readableDatabase
|
||||
var cursor: Cursor? = null
|
||||
val result = mutableMapOf<Long, LokiPublicChat>()
|
||||
val result = mutableMapOf<Long, PublicChat>()
|
||||
try {
|
||||
cursor = database.rawQuery("select * from $publicChatTableName", null)
|
||||
cursor = database.rawQuery("select * from $publicChatTable", null)
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
val threadID = cursor.getLong(threadID)
|
||||
val string = cursor.getString(publicChat)
|
||||
val publicChat = LokiPublicChat.fromJSON(string)
|
||||
val publicChat = PublicChat.fromJSON(string)
|
||||
if (publicChat != null) { result[threadID] = publicChat }
|
||||
}
|
||||
} 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) }
|
||||
}
|
||||
|
||||
override fun getPublicChat(threadID: Long): LokiPublicChat? {
|
||||
override fun getPublicChat(threadID: Long): PublicChat? {
|
||||
if (threadID < 0) { return null }
|
||||
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)
|
||||
LokiPublicChat.fromJSON(publicChatAsJSON)
|
||||
PublicChat.fromJSON(publicChatAsJSON)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setPublicChat(publicChat: LokiPublicChat, threadID: Long) {
|
||||
override fun setPublicChat(publicChat: PublicChat, threadID: Long) {
|
||||
if (threadID < 0) { return }
|
||||
val database = databaseHelper.writableDatabase
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.threadID, threadID)
|
||||
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) {
|
||||
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()
|
||||
if (devices.add(hexEncodedPublicKey)) {
|
||||
if (devices.add(publicKey)) {
|
||||
TextSecurePreferences.setStringPreference(context, "session_restore_devices_$threadID", devices.joinToString(","))
|
||||
delegate?.handleSessionRestoreDevicesChanged(threadID)
|
||||
}
|
||||
|
@ -20,60 +20,60 @@ class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database
|
||||
private val displayName = "display_name"
|
||||
// Display name cache
|
||||
private val displayNameTable = "loki_user_display_name_database"
|
||||
private val hexEncodedPublicKey = "hex_encoded_public_key"
|
||||
@JvmStatic val createDisplayNameTableCommand = "CREATE TABLE $displayNameTable ($hexEncodedPublicKey TEXT PRIMARY KEY, $displayName TEXT);"
|
||||
private val publicKey = "hex_encoded_public_key"
|
||||
@JvmStatic val createDisplayNameTableCommand = "CREATE TABLE $displayNameTable ($publicKey TEXT PRIMARY KEY, $displayName TEXT);"
|
||||
// Server display name cache
|
||||
private val serverDisplayNameTable = "loki_user_server_display_name_database"
|
||||
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? {
|
||||
if (hexEncodedPublicKey == TextSecurePreferences.getLocalNumber(context)) {
|
||||
override fun getDisplayName(publicKey: String): String? {
|
||||
if (publicKey == TextSecurePreferences.getLocalNumber(context)) {
|
||||
return TextSecurePreferences.getProfileName(context)
|
||||
} else {
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setDisplayName(hexEncodedPublicKey: String, displayName: String) {
|
||||
fun setDisplayName(publicKey: String, displayName: String) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val row = ContentValues(2)
|
||||
row.put(Companion.hexEncodedPublicKey, hexEncodedPublicKey)
|
||||
row.put(Companion.publicKey, publicKey)
|
||||
row.put(Companion.displayName, displayName)
|
||||
database.insertOrUpdate(displayNameTable, row, "${Companion.hexEncodedPublicKey} = ?", arrayOf( hexEncodedPublicKey ))
|
||||
Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false).notifyListeners()
|
||||
database.insertOrUpdate(displayNameTable, row, "${Companion.publicKey} = ?", arrayOf( publicKey ))
|
||||
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
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
fun setServerDisplayName(serverID: String, hexEncodedPublicKey: String, displayName: String) {
|
||||
fun setServerDisplayName(serverID: String, publicKey: String, displayName: String) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val values = ContentValues(3)
|
||||
values.put(Companion.serverID, serverID)
|
||||
values.put(Companion.hexEncodedPublicKey, hexEncodedPublicKey)
|
||||
values.put(Companion.publicKey, publicKey)
|
||||
values.put(Companion.displayName, displayName)
|
||||
try {
|
||||
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) {
|
||||
Log.d("Loki", "Couldn't save server display name due to exception: $e.")
|
||||
}
|
||||
}
|
||||
|
||||
override fun getProfilePictureURL(hexEncodedPublicKey: String): String? {
|
||||
return if (hexEncodedPublicKey == TextSecurePreferences.getLocalNumber(context)) {
|
||||
override fun getProfilePictureURL(publicKey: String): String? {
|
||||
return if (publicKey == TextSecurePreferences.getLocalNumber(context)) {
|
||||
TextSecurePreferences.getProfilePictureURL(context)
|
||||
} 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.Util
|
||||
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.protocol.multidevice.DeviceLink
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLinkingSession
|
||||
@ -52,7 +52,7 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
|
||||
}
|
||||
|
||||
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 {
|
||||
this.deviceLink = deviceLink
|
||||
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.explanationTextView.text = resources.getString(R.string.dialog_link_device_master_mode_explanation_2)
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -84,7 +84,7 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
|
||||
contentView.cancelButton.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)
|
||||
}.success {
|
||||
TextSecurePreferences.setMultiDevice(context!!, true)
|
||||
@ -92,8 +92,8 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
|
||||
delegate?.onDeviceLinkRequestAuthorized()
|
||||
dismiss()
|
||||
}.fail {
|
||||
LokiFileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(context!!).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey)
|
||||
FileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(context!!).removePreKeyBundle(deviceLink.slavePublicKey)
|
||||
}.failUi {
|
||||
delegate?.onDeviceLinkAuthorizationFailed()
|
||||
dismiss()
|
||||
@ -104,7 +104,7 @@ class LinkDeviceMasterModeDialog : DialogFragment(), DeviceLinkingSessionListene
|
||||
DeviceLinkingSession.shared.stopListeningForLinkingRequests()
|
||||
DeviceLinkingSession.shared.removeListener(this)
|
||||
if (deviceLink != null) {
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(context).removePreKeyBundle(deviceLink!!.slaveHexEncodedPublicKey)
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(context).removePreKeyBundle(deviceLink!!.slavePublicKey)
|
||||
}
|
||||
dismiss()
|
||||
delegate?.onDeviceLinkCanceled()
|
||||
|
@ -41,7 +41,7 @@ class LinkDeviceSlaveModeDialog : DialogFragment(), DeviceLinkingSessionListener
|
||||
}
|
||||
|
||||
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 {
|
||||
this.deviceLink = deviceLink
|
||||
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.push.SignalServiceAddress
|
||||
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 java.util.*
|
||||
|
||||
@ -32,7 +32,7 @@ object ClosedGroupsProtocol {
|
||||
if (!conversation.address.isClosedGroup || groupID == null) { return false }
|
||||
// A closed group's members should never include slave devices
|
||||
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 publicKeyToCheckFor = senderMasterPublicKey ?: senderPublicKey
|
||||
val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupID, true)
|
||||
@ -57,7 +57,7 @@ object ClosedGroupsProtocol {
|
||||
} else {
|
||||
// A closed group's members should never include slave devices
|
||||
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 ->
|
||||
MultiDeviceProtocol.shared.getAllLinkedDevices(member.address.serialize()).map { Address.fromSerialized(it) }
|
||||
}.toMutableSet()
|
||||
@ -106,7 +106,7 @@ object ClosedGroupsProtocol {
|
||||
allDevices.remove(userPublicKey)
|
||||
}
|
||||
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) {
|
||||
// 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.
|
||||
if (content.isFriendRequest) { return }
|
||||
val recipient = recipient(context, publicKey)
|
||||
// Friend requests don't apply to groups
|
||||
if (recipient.isGroupRecipient) { return }
|
||||
@ -200,7 +199,6 @@ object FriendRequestProtocol {
|
||||
|
||||
@JvmStatic
|
||||
fun handleFriendRequestMessageIfNeeded(context: Context, publicKey: String, content: SignalServiceContent) {
|
||||
if (!content.isFriendRequest) { return }
|
||||
val recipient = recipient(context, publicKey)
|
||||
// Friend requests don't apply to groups
|
||||
if (recipient.isGroupRecipient) { return }
|
||||
@ -241,7 +239,7 @@ object FriendRequestProtocol {
|
||||
|
||||
@JvmStatic
|
||||
fun isFriendRequestFromBeforeRestoration(context: Context, content: SignalServiceContent): Boolean {
|
||||
return content.isFriendRequest && content.timestamp < TextSecurePreferences.getRestorationTime(context)
|
||||
return content.timestamp < TextSecurePreferences.getRestorationTime(context)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
@ -3,30 +3,30 @@ package org.thoughtcrime.securesms.loki.protocol
|
||||
import android.content.Context
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.whispersystems.libsignal.loki.LokiSessionResetProtocol
|
||||
import org.whispersystems.libsignal.loki.LokiSessionResetStatus
|
||||
import org.whispersystems.libsignal.loki.SessionResetProtocol
|
||||
import org.whispersystems.libsignal.loki.SessionResetStatus
|
||||
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 {
|
||||
return DatabaseFactory.getLokiThreadDatabase(context).getSessionResetStatus(hexEncodedPublicKey)
|
||||
override fun getSessionResetStatus(publicKey: String): SessionResetStatus {
|
||||
return DatabaseFactory.getLokiThreadDatabase(context).getSessionResetStatus(publicKey)
|
||||
}
|
||||
|
||||
override fun setSessionResetStatus(hexEncodedPublicKey: String, sessionResetStatus: LokiSessionResetStatus) {
|
||||
return DatabaseFactory.getLokiThreadDatabase(context).setSessionResetStatus(hexEncodedPublicKey, sessionResetStatus)
|
||||
override fun setSessionResetStatus(publicKey: String, sessionResetStatus: SessionResetStatus) {
|
||||
return DatabaseFactory.getLokiThreadDatabase(context).setSessionResetStatus(publicKey, sessionResetStatus)
|
||||
}
|
||||
|
||||
override fun onNewSessionAdopted(hexEncodedPublicKey: String, oldSessionResetStatus: LokiSessionResetStatus) {
|
||||
if (oldSessionResetStatus == LokiSessionResetStatus.IN_PROGRESS) {
|
||||
val ephemeralMessage = EphemeralMessage.create(hexEncodedPublicKey)
|
||||
override fun onNewSessionAdopted(publicKey: String, oldSessionResetStatus: SessionResetStatus) {
|
||||
if (oldSessionResetStatus == SessionResetStatus.IN_PROGRESS) {
|
||||
val ephemeralMessage = EphemeralMessage.create(publicKey)
|
||||
ApplicationContext.getInstance(context).jobManager.add(PushEphemeralMessageSendJob(ephemeralMessage))
|
||||
}
|
||||
// TODO: Show session reset succeed message
|
||||
}
|
||||
|
||||
override fun validatePreKeySignalMessage(sender: String, message: PreKeySignalMessage) {
|
||||
val preKeyRecord = DatabaseFactory.getLokiPreKeyRecordDatabase(context).getPreKeyRecord(sender) ?: return
|
||||
override fun validatePreKeySignalMessage(publicKey: String, message: PreKeySignalMessage) {
|
||||
val preKeyRecord = DatabaseFactory.getLokiPreKeyRecordDatabase(context).getPreKeyRecord(publicKey) ?: return
|
||||
// TODO: Checking that the pre key record isn't null is causing issues when it shouldn't
|
||||
check(preKeyRecord.id == (message.preKeyId ?: -1)) { "Received a background message from an unknown source." }
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import org.thoughtcrime.securesms.logging.Log
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender
|
||||
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 javax.inject.Inject
|
||||
|
||||
@ -43,7 +43,7 @@ class MultiDeviceOpenGroupUpdateJob private constructor(parameters: Parameters)
|
||||
return
|
||||
}
|
||||
// Gather open groups
|
||||
val openGroups = mutableListOf<LokiPublicChat>()
|
||||
val openGroups = mutableListOf<PublicChat>()
|
||||
DatabaseFactory.getGroupDatabase(context).groups.use { reader ->
|
||||
while (true) {
|
||||
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.SignalServiceDataMessage
|
||||
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.multidevice.DeviceLink
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLinkingSession
|
||||
@ -80,7 +80,7 @@ object MultiDeviceProtocol {
|
||||
}
|
||||
}
|
||||
val publicKey = recipient.address.serialize()
|
||||
LokiFileServerAPI.shared.getDeviceLinks(publicKey).success {
|
||||
FileServerAPI.shared.getDeviceLinks(publicKey).success {
|
||||
val devices = MultiDeviceProtocol.shared.getAllLinkedDevices(publicKey)
|
||||
val jobs = devices.map { sendMessagePushToDevice(context, recipient(context, it), messageID, messageType, isEndSession) }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@ -105,7 +105,7 @@ object MultiDeviceProtocol {
|
||||
// A request should include a pre key bundle. An authorization should be a normal message.
|
||||
if (deviceLink.type == DeviceLink.Type.REQUEST) {
|
||||
val preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(address.number)
|
||||
message.asFriendRequest(true).withPreKeyBundle(preKeyBundle)
|
||||
message.withPreKeyBundle(preKeyBundle)
|
||||
} else {
|
||||
// Include the user's profile key so that the slave device can get the user's profile picture
|
||||
message.withProfileKey(ProfileKeyUtil.getProfileKey(context))
|
||||
@ -135,7 +135,7 @@ object MultiDeviceProtocol {
|
||||
return Promise.ofFail(Exception("Failed to sign device link."))
|
||||
}
|
||||
return retryIfNeeded(8) {
|
||||
sendDeviceLinkMessage(context, deviceLink.slaveHexEncodedPublicKey, signedDeviceLink)
|
||||
sendDeviceLinkMessage(context, deviceLink.slavePublicKey, signedDeviceLink)
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ object MultiDeviceProtocol {
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
if (deviceLink.type == DeviceLink.Type.REQUEST) {
|
||||
handleDeviceLinkRequestMessage(context, deviceLink, content)
|
||||
} else if (deviceLink.slaveHexEncodedPublicKey == userPublicKey) {
|
||||
} else if (deviceLink.slavePublicKey == userPublicKey) {
|
||||
handleDeviceLinkAuthorizedMessage(context, deviceLink, content)
|
||||
}
|
||||
}
|
||||
@ -158,10 +158,10 @@ object MultiDeviceProtocol {
|
||||
} else if (isRequest && TextSecurePreferences.getMasterHexEncodedPublicKey(context) != null) {
|
||||
Log.d("Loki", "Ignoring unexpected device link message (the device is a slave device).")
|
||||
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.")
|
||||
return false
|
||||
} else if (isRequest && deviceLink.slaveHexEncodedPublicKey == userPublicKey) {
|
||||
} else if (isRequest && deviceLink.slavePublicKey == userPublicKey) {
|
||||
Log.d("Loki", "Ignoring device linking request message from self.")
|
||||
return false
|
||||
}
|
||||
@ -193,9 +193,9 @@ object MultiDeviceProtocol {
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
DatabaseFactory.getLokiAPIDatabase(context).clearDeviceLinks(userPublicKey)
|
||||
DatabaseFactory.getLokiAPIDatabase(context).addDeviceLink(deviceLink)
|
||||
TextSecurePreferences.setMasterHexEncodedPublicKey(context, deviceLink.masterHexEncodedPublicKey)
|
||||
TextSecurePreferences.setMasterHexEncodedPublicKey(context, deviceLink.masterPublicKey)
|
||||
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.duplicate_handleProfileKey(context, content)
|
||||
}
|
||||
@ -210,19 +210,19 @@ object MultiDeviceProtocol {
|
||||
// Ignore the request if we don't know about the device link in question
|
||||
val masterDeviceLinks = DatabaseFactory.getLokiAPIDatabase(context).getDeviceLinks(masterDevicePublicKey)
|
||||
if (masterDeviceLinks.none {
|
||||
it.masterHexEncodedPublicKey == masterDevicePublicKey && it.slaveHexEncodedPublicKey == userPublicKey
|
||||
it.masterPublicKey == masterDevicePublicKey && it.slavePublicKey == userPublicKey
|
||||
}) {
|
||||
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.
|
||||
// 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.
|
||||
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
|
||||
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)
|
||||
ApplicationContext.getInstance(context).clearData()
|
||||
|
@ -44,12 +44,11 @@ class PushEphemeralMessageSendJob private constructor(parameters: Parameters, pr
|
||||
// Attach a pre key bundle if needed
|
||||
if (message.get("friendRequest", false)) {
|
||||
val bundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(recipient)
|
||||
dataMessage.withPreKeyBundle(bundle).asFriendRequest(true)
|
||||
dataMessage.withPreKeyBundle(bundle)
|
||||
}
|
||||
// Set flags if needed (these are mutually exclusive)
|
||||
when {
|
||||
message.get("unpairingRequest", false) -> dataMessage.asUnlinkingRequest(true)
|
||||
message.get("sessionRestore", false) -> dataMessage.asSessionRestorationRequest(true)
|
||||
message.get("unpairingRequest", false) -> dataMessage.asDeviceUnlinkingRequest(true)
|
||||
message.get("sessionRequest", false) -> dataMessage.asSessionRequest(true)
|
||||
}
|
||||
// Send the message
|
||||
|
@ -56,7 +56,7 @@ class PushNullMessageSendJob private constructor(parameters: Parameters, private
|
||||
try {
|
||||
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess,
|
||||
Date().time, serializedContentMessage, false, ttl, false,
|
||||
false, false, false, false)
|
||||
false, false, false)
|
||||
} catch (e: Exception) {
|
||||
Log.d("Loki", "Failed to send null message to: $publicKey due to error: $e.")
|
||||
throw e
|
||||
|
@ -13,7 +13,7 @@ import org.thoughtcrime.securesms.loki.utilities.recipient
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
|
||||
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.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import java.util.*
|
||||
@ -93,7 +93,7 @@ object SessionManagementProtocol {
|
||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
Log.d("Loki", "Received a session reset request from: ${content.sender}; archiving the session.")
|
||||
sessionStore.archiveAllSessions(content.sender)
|
||||
lokiThreadDB.setSessionResetStatus(content.sender, LokiSessionResetStatus.REQUEST_RECEIVED)
|
||||
lokiThreadDB.setSessionResetStatus(content.sender, SessionResetStatus.REQUEST_RECEIVED)
|
||||
Log.d("Loki", "Sending an ephemeral message back to: ${content.sender}.")
|
||||
val ephemeralMessage = EphemeralMessage.create(content.sender)
|
||||
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.DeviceContactsInputStream
|
||||
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.todo.LokiMessageFriendRequestStatus
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
@ -151,7 +151,7 @@ object SyncMessagesProtocol {
|
||||
}
|
||||
|
||||
@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 allUserDevices = MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey)
|
||||
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 x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, SignalServiceGroup.GroupType.RSS_FEED, null, null, null, null)
|
||||
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())
|
||||
}
|
||||
}.fail { exception ->
|
||||
|
@ -47,7 +47,7 @@ object ContactUtilities {
|
||||
var isSlave = false
|
||||
if (!recipient.isGroupRecipient) {
|
||||
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))
|
||||
}
|
||||
|
@ -8,20 +8,20 @@ import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat
|
||||
import org.whispersystems.signalservice.loki.api.opengroups.PublicChat
|
||||
|
||||
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
|
||||
val groupID = LokiPublicChat.getId(channel, url)
|
||||
val groupID = PublicChat.getId(channel, url)
|
||||
val threadID = GroupManager.getOpenGroupThreadID(groupID, context)
|
||||
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
||||
if (openGroup != null) { return Promise.of(openGroup) }
|
||||
// Add the new group
|
||||
val application = ApplicationContext.getInstance(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 ->
|
||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastMessageServerID(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 network.loki.messenger.R
|
||||
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
|
||||
|
||||
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() {
|
||||
displayNameTextView.text = mentionCandidate.displayName
|
||||
profilePictureView.hexEncodedPublicKey = mentionCandidate.hexEncodedPublicKey
|
||||
profilePictureView.hexEncodedPublicKey = mentionCandidate.publicKey
|
||||
profilePictureView.additionalHexEncodedPublicKey = null
|
||||
profilePictureView.isRSSFeed = false
|
||||
profilePictureView.glide = glide!!
|
||||
profilePictureView.update()
|
||||
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
|
||||
} else {
|
||||
moderatorIconImageView.visibility = View.GONE
|
||||
|
@ -3,7 +3,7 @@ package org.thoughtcrime.securesms.mms;
|
||||
import android.content.Context;
|
||||
|
||||
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 {
|
||||
|
||||
@ -22,26 +22,26 @@ public class PushMediaConstraints extends MediaConstraints {
|
||||
|
||||
@Override
|
||||
public int getImageMaxSize(Context context) {
|
||||
return LokiFileServerAPI.Companion.getMaxFileSize();
|
||||
return FileServerAPI.Companion.getMaxFileSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGifMaxSize(Context context) {
|
||||
return LokiFileServerAPI.Companion.getMaxFileSize();
|
||||
return FileServerAPI.Companion.getMaxFileSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVideoMaxSize(Context context) {
|
||||
return LokiFileServerAPI.Companion.getMaxFileSize();
|
||||
return FileServerAPI.Companion.getMaxFileSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAudioMaxSize(Context context) {
|
||||
return LokiFileServerAPI.Companion.getMaxFileSize();
|
||||
return FileServerAPI.Companion.getMaxFileSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
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 org.thoughtcrime.securesms.crypto.SecurityEvent;
|
||||
import org.thoughtcrime.securesms.loki.protocol.FriendRequestProtocol;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
@ -18,19 +17,4 @@ public class MessageSenderEventListener implements SignalServiceMessageSender.Ev
|
||||
public void onSecurityEvent(SignalServiceAddress textSecureAddress) {
|
||||
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