mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00:00
clean up V1 closed group
This commit is contained in:
parent
fde45f755b
commit
20ec889730
@ -76,7 +76,6 @@ import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
|||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.SharedSenderKeysDatabase;
|
import org.thoughtcrime.securesms.loki.database.SharedSenderKeysDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
|
|
||||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation;
|
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
|
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
|
||||||
@ -139,8 +138,7 @@ import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
|
|||||||
*
|
*
|
||||||
* @author Moxie Marlinspike
|
* @author Moxie Marlinspike
|
||||||
*/
|
*/
|
||||||
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate,
|
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate {
|
||||||
SessionManagementProtocolDelegate, SharedSenderKeysImplementationDelegate {
|
|
||||||
|
|
||||||
private static final String TAG = ApplicationContext.class.getSimpleName();
|
private static final String TAG = ApplicationContext.class.getSimpleName();
|
||||||
private final static int OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10 MB
|
private final static int OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10 MB
|
||||||
@ -191,7 +189,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
SharedSenderKeysDatabase sskDatabase = DatabaseFactory.getSSKDatabase(this);
|
SharedSenderKeysDatabase sskDatabase = DatabaseFactory.getSSKDatabase(this);
|
||||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||||
SessionResetImplementation sessionResetImpl = new SessionResetImplementation(this);
|
SessionResetImplementation sessionResetImpl = new SessionResetImplementation(this);
|
||||||
SharedSenderKeysImplementation.Companion.configureIfNeeded(sskDatabase, this);
|
|
||||||
MessagingConfiguration.Companion.configure(this,
|
MessagingConfiguration.Companion.configure(this,
|
||||||
DatabaseFactory.getStorage(this),
|
DatabaseFactory.getStorage(this),
|
||||||
sskDatabase,
|
sskDatabase,
|
||||||
@ -203,7 +200,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
||||||
SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||||
}
|
}
|
||||||
SessionManagementProtocol.Companion.configureIfNeeded(sessionResetImpl, sskDatabase, this);
|
|
||||||
setUpP2PAPIIfNeeded();
|
setUpP2PAPIIfNeeded();
|
||||||
PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG);
|
PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG);
|
||||||
setUpStorageAPIIfNeeded();
|
setUpStorageAPIIfNeeded();
|
||||||
@ -542,7 +538,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
String encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this);
|
String encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this);
|
||||||
byte[] profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(encodedProfileKey);
|
byte[] profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(encodedProfileKey);
|
||||||
try {
|
try {
|
||||||
File profilePicture = AvatarHelper.getAvatarFile(this, Address.Companion.fromSerialized(userPublicKey));
|
File profilePicture = AvatarHelper.getAvatarFile(this, Address.fromSerialized(userPublicKey));
|
||||||
StreamDetails stream = new StreamDetails(new FileInputStream(profilePicture), "image/jpeg", profilePicture.length());
|
StreamDetails stream = new StreamDetails(new FileInputStream(profilePicture), "image/jpeg", profilePicture.length());
|
||||||
FileServerAPI.shared.uploadProfilePicture(FileServerAPI.shared.getServer(), profileKey, stream, () -> {
|
FileServerAPI.shared.uploadProfilePicture(FileServerAPI.shared.getServer(), profileKey, stream, () -> {
|
||||||
TextSecurePreferences.setLastProfilePictureUpload(this, new Date().getTime());
|
TextSecurePreferences.setLastProfilePictureUpload(this, new Date().getTime());
|
||||||
@ -569,7 +565,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
String url = TextSecurePreferences.getProfilePictureURL(this);
|
String url = TextSecurePreferences.getProfilePictureURL(this);
|
||||||
String userMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(this);
|
String userMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(this);
|
||||||
if (userMasterDevice != null) {
|
if (userMasterDevice != null) {
|
||||||
Recipient userMasterDeviceAsRecipient = Recipient.from(this, Address.Companion.fromSerialized(userMasterDevice), false).resolve();
|
Recipient userMasterDeviceAsRecipient = Recipient.from(this, Address.fromSerialized(userMasterDevice), false).resolve();
|
||||||
profileKey = userMasterDeviceAsRecipient.getProfileKey();
|
profileKey = userMasterDeviceAsRecipient.getProfileKey();
|
||||||
url = userMasterDeviceAsRecipient.getProfileAvatar();
|
url = userMasterDeviceAsRecipient.getProfileAvatar();
|
||||||
}
|
}
|
||||||
@ -608,25 +604,5 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
|||||||
Runtime.getRuntime().exit(0);
|
Runtime.getRuntime().exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public boolean hasSentSessionRequestExpired(@NotNull String publicKey) {
|
|
||||||
// LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
|
|
||||||
// Long timestamp = apiDB.getSessionRequestSentTimestamp(publicKey);
|
|
||||||
// if (timestamp != null) {
|
|
||||||
// long expiration = timestamp + TTLUtilities.getTTL(TTLUtilities.MessageType.SessionRequest);
|
|
||||||
// return new Date().getTime() > expiration;
|
|
||||||
// } else {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendSessionRequestIfNeeded(@NotNull String publicKey) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void requestSenderKey(@NotNull String groupPublicKey, @NotNull String senderPublicKey) {
|
|
||||||
ClosedGroupsProtocol.requestSenderKey(this, groupPublicKey, senderPublicKey);
|
|
||||||
}
|
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity {
|
|||||||
if (address == null) throw new AssertionError();
|
if (address == null) throw new AssertionError();
|
||||||
if (locale == null) throw new AssertionError();
|
if (locale == null) throw new AssertionError();
|
||||||
|
|
||||||
this.recipient = Recipient.from(getContext(), Address.Companion.fromSerialized(address), true);
|
this.recipient = Recipient.from(getContext(), Address.fromSerialized(address), true);
|
||||||
this.locale = locale;
|
this.locale = locale;
|
||||||
|
|
||||||
getLoaderManager().initLoader(0, null, this);
|
getLoaderManager().initLoader(0, null, this);
|
||||||
|
@ -250,7 +250,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContactSelected(String number) {
|
public void onContactSelected(String number) {
|
||||||
Recipient recipient = Recipient.from(this, Address.Companion.fromExternal(this, number), true);
|
Recipient recipient = Recipient.from(this, Address.fromExternal(this, number), true);
|
||||||
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient);
|
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient);
|
||||||
createConversation(existingThread, recipient.getAddress(), ThreadDatabase.DistributionTypes.DEFAULT);
|
createConversation(existingThread, recipient.getAddress(), ThreadDatabase.DistributionTypes.DEFAULT);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ public class ShortcutLauncherActivity extends AppCompatActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Address address = Address.Companion.fromSerialized(serializedAddress);
|
Address address = Address.fromSerialized(serializedAddress);
|
||||||
Recipient recipient = Recipient.from(this, address, true);
|
Recipient recipient = Recipient.from(this, address, true);
|
||||||
TaskStackBuilder backStack = TaskStackBuilder.create(this)
|
TaskStackBuilder backStack = TaskStackBuilder.create(this)
|
||||||
.addNextIntent(new Intent(this, HomeActivity.class));
|
.addNextIntent(new Intent(this, HomeActivity.class));
|
||||||
|
@ -113,7 +113,7 @@ public class AvatarImageView extends AppCompatImageView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void update(String hexEncodedPublicKey) {
|
public void update(String hexEncodedPublicKey) {
|
||||||
Address address = Address.Companion.fromSerialized(hexEncodedPublicKey);
|
Address address = Address.fromSerialized(hexEncodedPublicKey);
|
||||||
Recipient recipient = Recipient.from(getContext(), address, false);
|
Recipient recipient = Recipient.from(getContext(), address, false);
|
||||||
updateAvatar(recipient);
|
updateAvatar(recipient);
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,7 @@ import org.greenrobot.eventbus.Subscribe;
|
|||||||
import org.greenrobot.eventbus.ThreadMode;
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
|
|
||||||
|
|
||||||
|
import org.session.libsession.utilities.GroupUtil;
|
||||||
import org.session.libsession.utilities.MediaTypes;
|
import org.session.libsession.utilities.MediaTypes;
|
||||||
import org.session.libsignal.libsignal.InvalidMessageException;
|
import org.session.libsignal.libsignal.InvalidMessageException;
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
@ -142,7 +143,6 @@ import org.thoughtcrime.securesms.loki.api.PublicChatInfoUpdateWorker;
|
|||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabaseDelegate;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabaseDelegate;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
|
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2;
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.GeneralUtilitiesKt;
|
import org.thoughtcrime.securesms.loki.utilities.GeneralUtilitiesKt;
|
||||||
@ -1100,7 +1100,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
String groupPublicKey;
|
String groupPublicKey;
|
||||||
boolean isSSKBasedClosedGroup;
|
boolean isSSKBasedClosedGroup;
|
||||||
try {
|
try {
|
||||||
groupPublicKey = HexEncodingKt.toHexString(ClosedGroupsProtocol.doubleDecodeGroupID(groupRecipient.getAddress().toString()));
|
groupPublicKey = HexEncodingKt.toHexString(GroupUtil.doubleDecodeGroupID(groupRecipient.getAddress().toString()));
|
||||||
isSSKBasedClosedGroup = DatabaseFactory.getSSKDatabase(this).isSSKBasedClosedGroup(groupPublicKey);
|
isSSKBasedClosedGroup = DatabaseFactory.getSSKDatabase(this).isSSKBasedClosedGroup(groupPublicKey);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
groupPublicKey = null;
|
groupPublicKey = null;
|
||||||
@ -1110,8 +1110,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
if (isSSKBasedClosedGroup) {
|
if (isSSKBasedClosedGroup) {
|
||||||
ClosedGroupsProtocolV2.explicitLeave(this, groupPublicKey);
|
ClosedGroupsProtocolV2.explicitLeave(this, groupPublicKey);
|
||||||
initializeEnabledCheck();
|
initializeEnabledCheck();
|
||||||
} else if (ClosedGroupsProtocol.leaveLegacyGroup(this, groupRecipient)) {
|
|
||||||
initializeEnabledCheck();
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
@ -2062,10 +2060,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
long result = MessageSender.send(context, outgoingMessage, threadId, forceSms, () -> fragment.releaseOutgoingMessage(id));
|
long result = MessageSender.send(context, outgoingMessage, threadId, forceSms, () -> fragment.releaseOutgoingMessage(id));
|
||||||
|
|
||||||
if (!recipient.isGroupRecipient()) {
|
|
||||||
ApplicationContext.getInstance(context).sendSessionRequestIfNeeded(recipient.getAddress().serialize());
|
|
||||||
}
|
|
||||||
|
|
||||||
sendComplete(result);
|
sendComplete(result);
|
||||||
future.set(null);
|
future.set(null);
|
||||||
|
|
||||||
@ -2092,10 +2086,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
long result = MessageSender.send(context, message, threadId, false, () -> fragment.releaseOutgoingMessage(id));
|
long result = MessageSender.send(context, message, threadId, false, () -> fragment.releaseOutgoingMessage(id));
|
||||||
|
|
||||||
if (!recipient.isGroupRecipient()) {
|
|
||||||
ApplicationContext.getInstance(context).sendSessionRequestIfNeeded(recipient.getAddress().serialize());
|
|
||||||
}
|
|
||||||
|
|
||||||
sendComplete(result);
|
sendComplete(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2517,7 +2507,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
Recipient author;
|
Recipient author;
|
||||||
|
|
||||||
if (messageRecord.isOutgoing()) {
|
if (messageRecord.isOutgoing()) {
|
||||||
author = Recipient.from(this, Address.Companion.fromSerialized(TextSecurePreferences.getLocalNumber(this)), true);
|
author = Recipient.from(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)), true);
|
||||||
} else {
|
} else {
|
||||||
author = messageRecord.getIndividualRecipient();
|
author = messageRecord.getIndividualRecipient();
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ public class TextSecureSessionStore implements SessionStore {
|
|||||||
@Override
|
@Override
|
||||||
public SessionRecord loadSession(@NonNull SignalProtocolAddress address) {
|
public SessionRecord loadSession(@NonNull SignalProtocolAddress address) {
|
||||||
synchronized (FILE_LOCK) {
|
synchronized (FILE_LOCK) {
|
||||||
SessionRecord sessionRecord = DatabaseFactory.getSessionDatabase(context).load(Address.Companion.fromSerialized(address.getName()), address.getDeviceId());
|
SessionRecord sessionRecord = DatabaseFactory.getSessionDatabase(context).load(Address.fromSerialized(address.getName()), address.getDeviceId());
|
||||||
|
|
||||||
if (sessionRecord == null) {
|
if (sessionRecord == null) {
|
||||||
Log.w(TAG, "No existing session information found.");
|
Log.w(TAG, "No existing session information found.");
|
||||||
@ -43,14 +43,14 @@ public class TextSecureSessionStore implements SessionStore {
|
|||||||
@Override
|
@Override
|
||||||
public void storeSession(@NonNull SignalProtocolAddress address, @NonNull SessionRecord record) {
|
public void storeSession(@NonNull SignalProtocolAddress address, @NonNull SessionRecord record) {
|
||||||
synchronized (FILE_LOCK) {
|
synchronized (FILE_LOCK) {
|
||||||
DatabaseFactory.getSessionDatabase(context).store(Address.Companion.fromSerialized(address.getName()), address.getDeviceId(), record);
|
DatabaseFactory.getSessionDatabase(context).store(Address.fromSerialized(address.getName()), address.getDeviceId(), record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean containsSession(SignalProtocolAddress address) {
|
public boolean containsSession(SignalProtocolAddress address) {
|
||||||
synchronized (FILE_LOCK) {
|
synchronized (FILE_LOCK) {
|
||||||
SessionRecord sessionRecord = DatabaseFactory.getSessionDatabase(context).load(Address.Companion.fromSerialized(address.getName()), address.getDeviceId());
|
SessionRecord sessionRecord = DatabaseFactory.getSessionDatabase(context).load(Address.fromSerialized(address.getName()), address.getDeviceId());
|
||||||
|
|
||||||
return sessionRecord != null &&
|
return sessionRecord != null &&
|
||||||
sessionRecord.getSessionState().hasSenderChain() &&
|
sessionRecord.getSessionState().hasSenderChain() &&
|
||||||
@ -61,27 +61,27 @@ public class TextSecureSessionStore implements SessionStore {
|
|||||||
@Override
|
@Override
|
||||||
public void deleteSession(SignalProtocolAddress address) {
|
public void deleteSession(SignalProtocolAddress address) {
|
||||||
synchronized (FILE_LOCK) {
|
synchronized (FILE_LOCK) {
|
||||||
DatabaseFactory.getSessionDatabase(context).delete(Address.Companion.fromSerialized(address.getName()), address.getDeviceId());
|
DatabaseFactory.getSessionDatabase(context).delete(Address.fromSerialized(address.getName()), address.getDeviceId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteAllSessions(String name) {
|
public void deleteAllSessions(String name) {
|
||||||
synchronized (FILE_LOCK) {
|
synchronized (FILE_LOCK) {
|
||||||
DatabaseFactory.getSessionDatabase(context).deleteAllFor(Address.Companion.fromSerialized(name));
|
DatabaseFactory.getSessionDatabase(context).deleteAllFor(Address.fromSerialized(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Integer> getSubDeviceSessions(String name) {
|
public List<Integer> getSubDeviceSessions(String name) {
|
||||||
synchronized (FILE_LOCK) {
|
synchronized (FILE_LOCK) {
|
||||||
return DatabaseFactory.getSessionDatabase(context).getSubDevices(Address.Companion.fromSerialized(name));
|
return DatabaseFactory.getSessionDatabase(context).getSubDevices(Address.fromSerialized(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void archiveSiblingSessions(@NonNull SignalProtocolAddress address) {
|
public void archiveSiblingSessions(@NonNull SignalProtocolAddress address) {
|
||||||
synchronized (FILE_LOCK) {
|
synchronized (FILE_LOCK) {
|
||||||
List<SessionDatabase.SessionRow> sessions = DatabaseFactory.getSessionDatabase(context).getAllFor(Address.Companion.fromSerialized(address.getName()));
|
List<SessionDatabase.SessionRow> sessions = DatabaseFactory.getSessionDatabase(context).getAllFor(Address.fromSerialized(address.getName()));
|
||||||
|
|
||||||
for (SessionDatabase.SessionRow row : sessions) {
|
for (SessionDatabase.SessionRow row : sessions) {
|
||||||
if (row.getDeviceId() != address.getDeviceId()) {
|
if (row.getDeviceId() != address.getDeviceId()) {
|
||||||
|
@ -129,7 +129,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
|
|
||||||
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {GROUP_ID},
|
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {GROUP_ID},
|
||||||
MEMBERS + " = ? AND " + MMS + " = ?",
|
MEMBERS + " = ? AND " + MMS + " = ?",
|
||||||
new String[] {Address.Companion.toSerializedList(members, ','), "1"},
|
new String[] {Address.toSerializedList(members, ','), "1"},
|
||||||
null, null, null);
|
null, null, null);
|
||||||
try {
|
try {
|
||||||
if (cursor != null && cursor.moveToNext()) {
|
if (cursor != null && cursor.moveToNext()) {
|
||||||
@ -179,7 +179,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
|
|
||||||
public boolean isClosedGroupMember(String hexEncodedPublicKey) {
|
public boolean isClosedGroupMember(String hexEncodedPublicKey) {
|
||||||
try {
|
try {
|
||||||
Address address = Address.Companion.fromSerialized(hexEncodedPublicKey);
|
Address address = Address.fromSerialized(hexEncodedPublicKey);
|
||||||
Reader reader = DatabaseFactory.getGroupDatabase(context).getGroups();
|
Reader reader = DatabaseFactory.getGroupDatabase(context).getGroups();
|
||||||
|
|
||||||
GroupRecord record;
|
GroupRecord record;
|
||||||
@ -203,7 +203,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
ContentValues contentValues = new ContentValues();
|
ContentValues contentValues = new ContentValues();
|
||||||
contentValues.put(GROUP_ID, groupId);
|
contentValues.put(GROUP_ID, groupId);
|
||||||
contentValues.put(TITLE, title);
|
contentValues.put(TITLE, title);
|
||||||
contentValues.put(MEMBERS, Address.Companion.toSerializedList(members, ','));
|
contentValues.put(MEMBERS, Address.toSerializedList(members, ','));
|
||||||
|
|
||||||
if (avatar != null) {
|
if (avatar != null) {
|
||||||
contentValues.put(AVATAR_ID, avatar.getId());
|
contentValues.put(AVATAR_ID, avatar.getId());
|
||||||
@ -219,12 +219,12 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
contentValues.put(MMS, GroupUtil.isMmsGroup(groupId));
|
contentValues.put(MMS, GroupUtil.isMmsGroup(groupId));
|
||||||
|
|
||||||
if (admins != null) {
|
if (admins != null) {
|
||||||
contentValues.put(ADMINS, Address.Companion.toSerializedList(admins, ','));
|
contentValues.put(ADMINS, Address.toSerializedList(admins, ','));
|
||||||
}
|
}
|
||||||
|
|
||||||
long threadId = databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues);
|
long threadId = databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues);
|
||||||
|
|
||||||
Recipient.applyCached(Address.Companion.fromSerialized(groupId), recipient -> {
|
Recipient.applyCached(Address.fromSerialized(groupId), recipient -> {
|
||||||
recipient.setName(title);
|
recipient.setName(title);
|
||||||
recipient.setGroupAvatarId(avatar != null ? avatar.getId() : null);
|
recipient.setGroupAvatarId(avatar != null ? avatar.getId() : null);
|
||||||
recipient.setParticipants(Stream.of(members).map(memberAddress -> Recipient.from(context, memberAddress, true)).toList());
|
recipient.setParticipants(Stream.of(members).map(memberAddress -> Recipient.from(context, memberAddress, true)).toList());
|
||||||
@ -238,7 +238,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
int result = databaseHelper.getWritableDatabase().delete(TABLE_NAME, GROUP_ID + " = ?", new String[]{groupId});
|
int result = databaseHelper.getWritableDatabase().delete(TABLE_NAME, GROUP_ID + " = ?", new String[]{groupId});
|
||||||
|
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
Recipient.removeCached(Address.Companion.fromSerialized(groupId));
|
Recipient.removeCached(Address.fromSerialized(groupId));
|
||||||
notifyConversationListListeners();
|
notifyConversationListListeners();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -262,7 +262,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
GROUP_ID + " = ?",
|
GROUP_ID + " = ?",
|
||||||
new String[] {groupId});
|
new String[] {groupId});
|
||||||
|
|
||||||
Recipient.applyCached(Address.Companion.fromSerialized(groupId), recipient -> {
|
Recipient.applyCached(Address.fromSerialized(groupId), recipient -> {
|
||||||
recipient.setName(title);
|
recipient.setName(title);
|
||||||
recipient.setGroupAvatarId(avatar != null ? avatar.getId() : null);
|
recipient.setGroupAvatarId(avatar != null ? avatar.getId() : null);
|
||||||
});
|
});
|
||||||
@ -277,7 +277,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
||||||
new String[] {groupID});
|
new String[] {groupID});
|
||||||
|
|
||||||
Recipient recipient = Recipient.from(context, Address.Companion.fromSerialized(groupID), false);
|
Recipient recipient = Recipient.from(context, Address.fromSerialized(groupID), false);
|
||||||
recipient.setName(newValue);
|
recipient.setName(newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,20 +300,20 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
||||||
new String[] {groupID});
|
new String[] {groupID});
|
||||||
|
|
||||||
Recipient.applyCached(Address.Companion.fromSerialized(groupID), recipient -> recipient.setGroupAvatarId(avatarId == 0 ? null : avatarId));
|
Recipient.applyCached(Address.fromSerialized(groupID), recipient -> recipient.setGroupAvatarId(avatarId == 0 ? null : avatarId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateMembers(String groupId, List<Address> members) {
|
public void updateMembers(String groupId, List<Address> members) {
|
||||||
Collections.sort(members);
|
Collections.sort(members);
|
||||||
|
|
||||||
ContentValues contents = new ContentValues();
|
ContentValues contents = new ContentValues();
|
||||||
contents.put(MEMBERS, Address.Companion.toSerializedList(members, ','));
|
contents.put(MEMBERS, Address.toSerializedList(members, ','));
|
||||||
contents.put(ACTIVE, 1);
|
contents.put(ACTIVE, 1);
|
||||||
|
|
||||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
||||||
new String[] {groupId});
|
new String[] {groupId});
|
||||||
|
|
||||||
Recipient.applyCached(Address.Companion.fromSerialized(groupId), recipient -> {
|
Recipient.applyCached(Address.fromSerialized(groupId), recipient -> {
|
||||||
recipient.setParticipants(Stream.of(members).map(a -> Recipient.from(context, a, false)).toList());
|
recipient.setParticipants(Stream.of(members).map(a -> Recipient.from(context, a, false)).toList());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -322,7 +322,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
Collections.sort(admins);
|
Collections.sort(admins);
|
||||||
|
|
||||||
ContentValues contents = new ContentValues();
|
ContentValues contents = new ContentValues();
|
||||||
contents.put(ADMINS, Address.Companion.toSerializedList(admins, ','));
|
contents.put(ADMINS, Address.toSerializedList(admins, ','));
|
||||||
contents.put(ACTIVE, 1);
|
contents.put(ACTIVE, 1);
|
||||||
|
|
||||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?", new String[] {groupId});
|
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?", new String[] {groupId});
|
||||||
@ -333,12 +333,12 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
currentMembers.remove(source);
|
currentMembers.remove(source);
|
||||||
|
|
||||||
ContentValues contents = new ContentValues();
|
ContentValues contents = new ContentValues();
|
||||||
contents.put(MEMBERS, Address.Companion.toSerializedList(currentMembers, ','));
|
contents.put(MEMBERS, Address.toSerializedList(currentMembers, ','));
|
||||||
|
|
||||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
||||||
new String[] {groupId});
|
new String[] {groupId});
|
||||||
|
|
||||||
Recipient.applyCached(Address.Companion.fromSerialized(groupId), recipient -> {
|
Recipient.applyCached(Address.fromSerialized(groupId), recipient -> {
|
||||||
List<Recipient> current = recipient.getParticipants();
|
List<Recipient> current = recipient.getParticipants();
|
||||||
Recipient removal = Recipient.from(context, source, false);
|
Recipient removal = Recipient.from(context, source, false);
|
||||||
|
|
||||||
@ -358,7 +358,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
String serializedMembers = cursor.getString(cursor.getColumnIndexOrThrow(MEMBERS));
|
String serializedMembers = cursor.getString(cursor.getColumnIndexOrThrow(MEMBERS));
|
||||||
return Address.Companion.fromSerializedList(serializedMembers, ',');
|
return Address.fromSerializedList(serializedMembers, ',');
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LinkedList<>();
|
return new LinkedList<>();
|
||||||
|
@ -82,7 +82,7 @@ public class GroupReceiptDatabase extends Database {
|
|||||||
|
|
||||||
try (Cursor cursor = db.query(TABLE_NAME, null, MMS_ID + " = ?", new String[] {String.valueOf(mmsId)}, null, null, null)) {
|
try (Cursor cursor = db.query(TABLE_NAME, null, MMS_ID + " = ?", new String[] {String.valueOf(mmsId)}, null, null, null)) {
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
results.add(new GroupReceiptInfo(Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS))),
|
results.add(new GroupReceiptInfo(Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS))),
|
||||||
cursor.getInt(cursor.getColumnIndexOrThrow(STATUS)),
|
cursor.getInt(cursor.getColumnIndexOrThrow(STATUS)),
|
||||||
cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP)),
|
cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP)),
|
||||||
cursor.getInt(cursor.getColumnIndexOrThrow(UNIDENTIFIED)) == 1));
|
cursor.getInt(cursor.getColumnIndexOrThrow(UNIDENTIFIED)) == 1));
|
||||||
|
@ -108,7 +108,7 @@ public class MediaDatabase extends Database {
|
|||||||
Address address = null;
|
Address address = null;
|
||||||
|
|
||||||
if (serializedAddress != null) {
|
if (serializedAddress != null) {
|
||||||
address = Address.Companion.fromSerialized(serializedAddress);
|
address = Address.fromSerialized(serializedAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
long date;
|
long date;
|
||||||
|
@ -268,7 +268,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
|
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
if (Types.isOutgoingMessageType(cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX)))) {
|
if (Types.isOutgoingMessageType(cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX)))) {
|
||||||
Address theirAddress = Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
Address theirAddress = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
||||||
Address ourAddress = messageId.getAddress();
|
Address ourAddress = messageId.getAddress();
|
||||||
String columnName = deliveryReceipt ? DELIVERY_RECEIPT_COUNT : READ_RECEIPT_COUNT;
|
String columnName = deliveryReceipt ? DELIVERY_RECEIPT_COUNT : READ_RECEIPT_COUNT;
|
||||||
|
|
||||||
@ -333,7 +333,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
String fromString = notification.getFrom() != null && notification.getFrom().getTextString() != null
|
String fromString = notification.getFrom() != null && notification.getFrom().getTextString() != null
|
||||||
? Util.toIsoString(notification.getFrom().getTextString())
|
? Util.toIsoString(notification.getFrom().getTextString())
|
||||||
: "";
|
: "";
|
||||||
Recipient recipient = Recipient.from(context, Address.Companion.fromExternal(context, fromString), false);
|
Recipient recipient = Recipient.from(context, Address.fromExternal(context, fromString), false);
|
||||||
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
|
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +500,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
|
|
||||||
while(cursor != null && cursor.moveToNext()) {
|
while(cursor != null && cursor.moveToNext()) {
|
||||||
if (Types.isSecureType(cursor.getLong(3))) {
|
if (Types.isSecureType(cursor.getLong(3))) {
|
||||||
SyncMessageId syncMessageId = new SyncMessageId(Address.Companion.fromSerialized(cursor.getString(1)), cursor.getLong(2));
|
SyncMessageId syncMessageId = new SyncMessageId(Address.fromSerialized(cursor.getString(1)), cursor.getLong(2));
|
||||||
ExpirationInfo expirationInfo = new ExpirationInfo(cursor.getLong(0), cursor.getLong(4), cursor.getLong(5), true);
|
ExpirationInfo expirationInfo = new ExpirationInfo(cursor.getLong(0), cursor.getLong(4), cursor.getLong(5), true);
|
||||||
|
|
||||||
result.add(new MarkedMessageInfo(syncMessageId, expirationInfo));
|
result.add(new MarkedMessageInfo(syncMessageId, expirationInfo));
|
||||||
@ -529,7 +529,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
cursor = database.query(TABLE_NAME, new String[] {ID, THREAD_ID, MESSAGE_BOX, EXPIRES_IN, EXPIRE_STARTED, ADDRESS}, DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())}, null, null, null, null);
|
cursor = database.query(TABLE_NAME, new String[] {ID, THREAD_ID, MESSAGE_BOX, EXPIRES_IN, EXPIRE_STARTED, ADDRESS}, DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())}, null, null, null, null);
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
Address theirAddress = Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
Address theirAddress = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
||||||
Address ourAddress = messageId.getAddress();
|
Address ourAddress = messageId.getAddress();
|
||||||
|
|
||||||
if (ourAddress.equals(theirAddress) || theirAddress.isGroup()) {
|
if (ourAddress.equals(theirAddress) || theirAddress.isGroup()) {
|
||||||
@ -642,13 +642,13 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
.filterNot(previewAttachments::contains)
|
.filterNot(previewAttachments::contains)
|
||||||
.map(a -> (Attachment)a).toList();
|
.map(a -> (Attachment)a).toList();
|
||||||
|
|
||||||
Recipient recipient = Recipient.from(context, Address.Companion.fromSerialized(address), false);
|
Recipient recipient = Recipient.from(context, Address.fromSerialized(address), false);
|
||||||
List<NetworkFailure> networkFailures = new LinkedList<>();
|
List<NetworkFailure> networkFailures = new LinkedList<>();
|
||||||
List<IdentityKeyMismatch> mismatches = new LinkedList<>();
|
List<IdentityKeyMismatch> mismatches = new LinkedList<>();
|
||||||
QuoteModel quote = null;
|
QuoteModel quote = null;
|
||||||
|
|
||||||
if (quoteId > 0 && (!TextUtils.isEmpty(quoteText) || !quoteAttachments.isEmpty())) {
|
if (quoteId > 0 && (!TextUtils.isEmpty(quoteText) || !quoteAttachments.isEmpty())) {
|
||||||
quote = new QuoteModel(quoteId, Address.Companion.fromSerialized(quoteAuthor), quoteText, quoteMissing, quoteAttachments);
|
quote = new QuoteModel(quoteId, Address.fromSerialized(quoteAuthor), quoteText, quoteMissing, quoteAttachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(mismatchDocument)) {
|
if (!TextUtils.isEmpty(mismatchDocument)) {
|
||||||
@ -955,7 +955,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
contentBuilder.add(MESSAGE_TYPE, notification.getMessageType());
|
contentBuilder.add(MESSAGE_TYPE, notification.getMessageType());
|
||||||
|
|
||||||
if (notification.getFrom() != null) {
|
if (notification.getFrom() != null) {
|
||||||
contentValues.put(ADDRESS, Address.Companion.fromExternal(context, Util.toIsoString(notification.getFrom().getTextString())).serialize());
|
contentValues.put(ADDRESS, Address.fromExternal(context, Util.toIsoString(notification.getFrom().getTextString())).serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
contentValues.put(MESSAGE_BOX, Types.BASE_INBOX_TYPE);
|
contentValues.put(MESSAGE_BOX, Types.BASE_INBOX_TYPE);
|
||||||
@ -1334,7 +1334,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
private final int subscriptionId;
|
private final int subscriptionId;
|
||||||
|
|
||||||
MmsNotificationInfo(@Nullable String from, String contentLocation, String transactionId, int subscriptionId) {
|
MmsNotificationInfo(@Nullable String from, String contentLocation, String transactionId, int subscriptionId) {
|
||||||
this.from = from == null ? null : Address.Companion.fromSerialized(from);
|
this.from = from == null ? null : Address.fromSerialized(from);
|
||||||
this.contentLocation = contentLocation;
|
this.contentLocation = contentLocation;
|
||||||
this.transactionId = transactionId;
|
this.transactionId = transactionId;
|
||||||
this.subscriptionId = subscriptionId;
|
this.subscriptionId = subscriptionId;
|
||||||
@ -1507,7 +1507,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
if (TextUtils.isEmpty(serialized) || "insert-address-token".equals(serialized)) {
|
if (TextUtils.isEmpty(serialized) || "insert-address-token".equals(serialized)) {
|
||||||
address = Address.Companion.getUNKNOWN();
|
address = Address.Companion.getUNKNOWN();
|
||||||
} else {
|
} else {
|
||||||
address = Address.Companion.fromSerialized(serialized);
|
address = Address.fromSerialized(serialized);
|
||||||
|
|
||||||
}
|
}
|
||||||
return Recipient.from(context, address, true);
|
return Recipient.from(context, address, true);
|
||||||
@ -1554,7 +1554,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
SlideDeck quoteDeck = new SlideDeck(context, quoteAttachments);
|
SlideDeck quoteDeck = new SlideDeck(context, quoteAttachments);
|
||||||
|
|
||||||
if (quoteId > 0 && !TextUtils.isEmpty(quoteAuthor)) {
|
if (quoteId > 0 && !TextUtils.isEmpty(quoteAuthor)) {
|
||||||
return new Quote(quoteId, Address.Companion.fromExternal(context, quoteAuthor), quoteText, quoteMissing, quoteDeck);
|
return new Quote(quoteId, Address.fromExternal(context, quoteAuthor), quoteText, quoteMissing, quoteDeck);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,7 @@ public class RecipientDatabase extends Database {
|
|||||||
|
|
||||||
try (Cursor cursor = db.query(TABLE_NAME, new String[] {ADDRESS}, null, null, null, null, null)) {
|
try (Cursor cursor = db.query(TABLE_NAME, new String[] {ADDRESS}, null, null, null, null, null)) {
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
results.add(Address.Companion.fromExternal(context, cursor.getString(0)));
|
results.add(Address.fromExternal(context, cursor.getString(0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +370,7 @@ public class RecipientDatabase extends Database {
|
|||||||
|
|
||||||
try (Cursor cursor = db.query(TABLE_NAME, new String[] {ADDRESS}, REGISTERED + " = ?", new String[] {"1"}, null, null, null)) {
|
try (Cursor cursor = db.query(TABLE_NAME, new String[] {ADDRESS}, REGISTERED + " = ?", new String[] {"1"}, null, null, null)) {
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
results.add(Address.Companion.fromSerialized(cursor.getString(0)));
|
results.add(Address.fromSerialized(cursor.getString(0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +383,7 @@ public class RecipientDatabase extends Database {
|
|||||||
|
|
||||||
try (Cursor cursor = db.query(TABLE_NAME, new String[] {ADDRESS}, SYSTEM_DISPLAY_NAME + " IS NOT NULL AND " + SYSTEM_DISPLAY_NAME + " != \"\"", null, null, null, null)) {
|
try (Cursor cursor = db.query(TABLE_NAME, new String[] {ADDRESS}, SYSTEM_DISPLAY_NAME + " IS NOT NULL AND " + SYSTEM_DISPLAY_NAME + " != \"\"", null, null, null, null)) {
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
results.add(Address.Companion.fromSerialized(cursor.getString(0)));
|
results.add(Address.fromSerialized(cursor.getString(0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +397,7 @@ public class RecipientDatabase extends Database {
|
|||||||
db.beginTransaction();
|
db.beginTransaction();
|
||||||
try (Cursor cursor = db.query(TABLE_NAME, new String[] {ADDRESS, COLOR, SYSTEM_DISPLAY_NAME}, SYSTEM_DISPLAY_NAME + " IS NOT NULL AND " + SYSTEM_DISPLAY_NAME + " != \"\"", null, null, null, null)) {
|
try (Cursor cursor = db.query(TABLE_NAME, new String[] {ADDRESS, COLOR, SYSTEM_DISPLAY_NAME}, SYSTEM_DISPLAY_NAME + " IS NOT NULL AND " + SYSTEM_DISPLAY_NAME + " != \"\"", null, null, null, null)) {
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
Address address = Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
||||||
MaterialColor newColor = updater.update(cursor.getString(cursor.getColumnIndexOrThrow(SYSTEM_DISPLAY_NAME)),
|
MaterialColor newColor = updater.update(cursor.getString(cursor.getColumnIndexOrThrow(SYSTEM_DISPLAY_NAME)),
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(COLOR)));
|
cursor.getString(cursor.getColumnIndexOrThrow(COLOR)));
|
||||||
|
|
||||||
@ -497,7 +497,7 @@ public class RecipientDatabase extends Database {
|
|||||||
|
|
||||||
public @NonNull Recipient getCurrent() {
|
public @NonNull Recipient getCurrent() {
|
||||||
String serialized = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS));
|
String serialized = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS));
|
||||||
return Recipient.from(context, Address.Companion.fromSerialized(serialized), false);
|
return Recipient.from(context, Address.fromSerialized(serialized), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable Recipient getNext() {
|
public @Nullable Recipient getNext() {
|
||||||
|
@ -102,7 +102,7 @@ public class SessionDatabase extends Database {
|
|||||||
try (Cursor cursor = database.query(TABLE_NAME, null, null, null, null, null, null)) {
|
try (Cursor cursor = database.query(TABLE_NAME, null, null, null, null, null, null)) {
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
try {
|
try {
|
||||||
results.add(new SessionRow(Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS))),
|
results.add(new SessionRow(Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS))),
|
||||||
cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE)),
|
cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE)),
|
||||||
new SessionRecord(cursor.getBlob(cursor.getColumnIndexOrThrow(RECORD)))));
|
new SessionRecord(cursor.getBlob(cursor.getColumnIndexOrThrow(RECORD)))));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -377,7 +377,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
if (Types.isOutgoingMessageType(cursor.getLong(cursor.getColumnIndexOrThrow(TYPE)))) {
|
if (Types.isOutgoingMessageType(cursor.getLong(cursor.getColumnIndexOrThrow(TYPE)))) {
|
||||||
Address theirAddress = messageId.getAddress();
|
Address theirAddress = messageId.getAddress();
|
||||||
Address ourAddress = Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
Address ourAddress = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
||||||
String columnName = deliveryReceipt ? DELIVERY_RECEIPT_COUNT : READ_RECEIPT_COUNT;
|
String columnName = deliveryReceipt ? DELIVERY_RECEIPT_COUNT : READ_RECEIPT_COUNT;
|
||||||
|
|
||||||
if (ourAddress.equals(theirAddress)) {
|
if (ourAddress.equals(theirAddress)) {
|
||||||
@ -418,7 +418,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
|
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
Address theirAddress = messageId.getAddress();
|
Address theirAddress = messageId.getAddress();
|
||||||
Address ourAddress = Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
Address ourAddress = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
||||||
|
|
||||||
if (ourAddress.equals(theirAddress)) {
|
if (ourAddress.equals(theirAddress)) {
|
||||||
long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
||||||
@ -469,7 +469,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
|
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
if (Types.isSecureType(cursor.getLong(3))) {
|
if (Types.isSecureType(cursor.getLong(3))) {
|
||||||
SyncMessageId syncMessageId = new SyncMessageId(Address.Companion.fromSerialized(cursor.getString(1)), cursor.getLong(2));
|
SyncMessageId syncMessageId = new SyncMessageId(Address.fromSerialized(cursor.getString(1)), cursor.getLong(2));
|
||||||
ExpirationInfo expirationInfo = new ExpirationInfo(cursor.getLong(0), cursor.getLong(4), cursor.getLong(5), false);
|
ExpirationInfo expirationInfo = new ExpirationInfo(cursor.getLong(0), cursor.getLong(4), cursor.getLong(5), false);
|
||||||
|
|
||||||
results.add(new MarkedMessageInfo(syncMessageId, expirationInfo));
|
results.add(new MarkedMessageInfo(syncMessageId, expirationInfo));
|
||||||
@ -937,7 +937,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
|
|
||||||
public SmsMessageRecord getCurrent() {
|
public SmsMessageRecord getCurrent() {
|
||||||
long messageId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.ID));
|
long messageId = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.ID));
|
||||||
Address address = Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS)));
|
Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS)));
|
||||||
int addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS_DEVICE_ID));
|
int addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS_DEVICE_ID));
|
||||||
long type = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.TYPE));
|
long type = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.TYPE));
|
||||||
long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.NORMALIZED_DATE_RECEIVED));
|
long dateReceived = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.NORMALIZED_DATE_RECEIVED));
|
||||||
|
@ -90,7 +90,7 @@ public class SmsMigrator {
|
|||||||
long threadId, SQLiteStatement statement)
|
long threadId, SQLiteStatement statement)
|
||||||
{
|
{
|
||||||
String theirAddress = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS));
|
String theirAddress = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS));
|
||||||
statement.bindString(1, Address.Companion.fromExternal(context, theirAddress).serialize());
|
statement.bindString(1, Address.fromExternal(context, theirAddress).serialize());
|
||||||
|
|
||||||
addIntToStatement(statement, cursor, 2, SmsDatabase.PERSON);
|
addIntToStatement(statement, cursor, 2, SmsDatabase.PERSON);
|
||||||
addIntToStatement(statement, cursor, 3, SmsDatabase.DATE_RECEIVED);
|
addIntToStatement(statement, cursor, 3, SmsDatabase.DATE_RECEIVED);
|
||||||
@ -137,7 +137,7 @@ public class SmsMigrator {
|
|||||||
String address = getTheirCanonicalAddress(context, theirRecipientId);
|
String address = getTheirCanonicalAddress(context, theirRecipientId);
|
||||||
|
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
recipientList.add(Recipient.from(context, Address.Companion.fromExternal(context, address), true));
|
recipientList.add(Recipient.from(context, Address.fromExternal(context, address), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ public class SmsMigrator {
|
|||||||
long ourThreadId = threadDatabase.getOrCreateThreadIdFor(ourRecipients.iterator().next());
|
long ourThreadId = threadDatabase.getOrCreateThreadIdFor(ourRecipients.iterator().next());
|
||||||
migrateConversation(context, listener, progress, theirThreadId, ourThreadId);
|
migrateConversation(context, listener, progress, theirThreadId, ourThreadId);
|
||||||
} else if (ourRecipients.size() > 1) {
|
} else if (ourRecipients.size() > 1) {
|
||||||
ourRecipients.add(Recipient.from(context, Address.Companion.fromSerialized(TextSecurePreferences.getLocalNumber(context)), true));
|
ourRecipients.add(Recipient.from(context, Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)), true));
|
||||||
|
|
||||||
List<Address> memberAddresses = new LinkedList<>();
|
List<Address> memberAddresses = new LinkedList<>();
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ public class SmsMigrator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String ourGroupId = DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(memberAddresses, null);
|
String ourGroupId = DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(memberAddresses, null);
|
||||||
Recipient ourGroupRecipient = Recipient.from(context, Address.Companion.fromSerialized(ourGroupId), true);
|
Recipient ourGroupRecipient = Recipient.from(context, Address.fromSerialized(ourGroupId), true);
|
||||||
long ourThreadId = threadDatabase.getOrCreateThreadIdFor(ourGroupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
long ourThreadId = threadDatabase.getOrCreateThreadIdFor(ourGroupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||||
|
|
||||||
migrateConversation(context, listener, progress, theirThreadId, ourThreadId);
|
migrateConversation(context, listener, progress, theirThreadId, ourThreadId);
|
||||||
|
@ -556,7 +556,7 @@ public class ThreadDatabase extends Database {
|
|||||||
cursor = db.query(TABLE_NAME, null, ID + " = ?", new String[] {threadId+""}, null, null, null);
|
cursor = db.query(TABLE_NAME, null, ID + " = ?", new String[] {threadId+""}, null, null, null);
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
Address address = Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
||||||
addressCache.put(threadId, address);
|
addressCache.put(threadId, address);
|
||||||
return Recipient.from(context, address, false);
|
return Recipient.from(context, address, false);
|
||||||
}
|
}
|
||||||
@ -735,7 +735,7 @@ public class ThreadDatabase extends Database {
|
|||||||
public ThreadRecord getCurrent() {
|
public ThreadRecord getCurrent() {
|
||||||
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.ID));
|
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.ID));
|
||||||
int distributionType = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.TYPE));
|
int distributionType = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.TYPE));
|
||||||
Address address = Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.ADDRESS)));
|
Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.ADDRESS)));
|
||||||
|
|
||||||
Optional<RecipientSettings> settings;
|
Optional<RecipientSettings> settings;
|
||||||
Optional<GroupRecord> groupRecord;
|
Optional<GroupRecord> groupRecord;
|
||||||
|
@ -41,7 +41,7 @@ public class IdentityKeyMismatch {
|
|||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public Address getAddress() {
|
public Address getAddress() {
|
||||||
return Address.Companion.fromSerialized(address);
|
return Address.fromSerialized(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentityKey getIdentityKey() {
|
public IdentityKey getIdentityKey() {
|
||||||
|
@ -18,7 +18,7 @@ public class NetworkFailure {
|
|||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public Address getAddress() {
|
public Address getAddress() {
|
||||||
return Address.Companion.fromSerialized(address);
|
return Address.fromSerialized(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,7 +73,7 @@ public class ConversationListLoader extends AbstractCursorLoader {
|
|||||||
List<Address> addresses = new LinkedList<>();
|
List<Address> addresses = new LinkedList<>();
|
||||||
|
|
||||||
for (String number : numbers) {
|
for (String number : numbers) {
|
||||||
addresses.add(Address.Companion.fromExternal(context, number));
|
addresses.add(Address.fromExternal(context, number));
|
||||||
}
|
}
|
||||||
|
|
||||||
return DatabaseFactory.getThreadDatabase(context).getFilteredConversationList(addresses);
|
return DatabaseFactory.getThreadDatabase(context).getFilteredConversationList(addresses);
|
||||||
|
@ -44,7 +44,7 @@ public class GroupManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static long getThreadIDFromGroupID(String groupID, @NonNull Context context) {
|
public static long getThreadIDFromGroupID(String groupID, @NonNull Context context) {
|
||||||
final Recipient groupRecipient = Recipient.from(context, Address.Companion.fromSerialized(groupID), false);
|
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupID), false);
|
||||||
return DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(groupRecipient);
|
return DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(groupRecipient);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,14 +69,14 @@ public class GroupManager {
|
|||||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||||
final String groupId = GroupUtil.getEncodedClosedGroupID(id.getBytes()); // TODO: The group id is double encoded here 2
|
final String groupId = GroupUtil.getEncodedClosedGroupID(id.getBytes()); // TODO: The group id is double encoded here 2
|
||||||
final Recipient groupRecipient = Recipient.from(context, Address.Companion.fromSerialized(groupId), false);
|
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false);
|
||||||
final Set<Address> memberAddresses = getMemberAddresses(members);
|
final Set<Address> memberAddresses = getMemberAddresses(members);
|
||||||
final Set<Address> adminAddresses = getMemberAddresses(admins);
|
final Set<Address> adminAddresses = getMemberAddresses(admins);
|
||||||
|
|
||||||
String masterPublicKeyOrNull = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
String masterPublicKeyOrNull = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||||
String masterPublicKey = masterPublicKeyOrNull != null ? masterPublicKeyOrNull : TextSecurePreferences.getLocalNumber(context);
|
String masterPublicKey = masterPublicKeyOrNull != null ? masterPublicKeyOrNull : TextSecurePreferences.getLocalNumber(context);
|
||||||
|
|
||||||
memberAddresses.add(Address.Companion.fromSerialized(masterPublicKey));
|
memberAddresses.add(Address.fromSerialized(masterPublicKey));
|
||||||
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>(adminAddresses), System.currentTimeMillis());
|
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>(adminAddresses), System.currentTimeMillis());
|
||||||
|
|
||||||
groupDatabase.updateProfilePicture(groupId, avatarBytes);
|
groupDatabase.updateProfilePicture(groupId, avatarBytes);
|
||||||
@ -100,10 +100,10 @@ public class GroupManager {
|
|||||||
{
|
{
|
||||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||||
final Recipient groupRecipient = Recipient.from(context, Address.Companion.fromSerialized(groupId), false);
|
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false);
|
||||||
final Set<Address> memberAddresses = new HashSet<>();
|
final Set<Address> memberAddresses = new HashSet<>();
|
||||||
|
|
||||||
memberAddresses.add(Address.Companion.fromSerialized(Objects.requireNonNull(TextSecurePreferences.getLocalNumber(context))));
|
memberAddresses.add(Address.fromSerialized(Objects.requireNonNull(TextSecurePreferences.getLocalNumber(context))));
|
||||||
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>(), System.currentTimeMillis());
|
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>(), System.currentTimeMillis());
|
||||||
|
|
||||||
groupDatabase.updateProfilePicture(groupId, avatarBytes);
|
groupDatabase.updateProfilePicture(groupId, avatarBytes);
|
||||||
@ -118,7 +118,7 @@ public class GroupManager {
|
|||||||
{
|
{
|
||||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||||
final ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
final ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||||
final Recipient groupRecipient = Recipient.from(context, Address.Companion.fromSerialized(groupId), false);
|
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false);
|
||||||
|
|
||||||
if (!groupDatabase.getGroup(groupId).isPresent()) {
|
if (!groupDatabase.getGroup(groupId).isPresent()) {
|
||||||
return false;
|
return false;
|
||||||
@ -145,7 +145,7 @@ public class GroupManager {
|
|||||||
final Set<Address> adminAddresses = getMemberAddresses(admins);
|
final Set<Address> adminAddresses = getMemberAddresses(admins);
|
||||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||||
|
|
||||||
memberAddresses.add(Address.Companion.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||||
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
|
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
|
||||||
groupDatabase.updateAdmins(groupId, new LinkedList<>(adminAddresses));
|
groupDatabase.updateAdmins(groupId, new LinkedList<>(adminAddresses));
|
||||||
groupDatabase.updateTitle(groupId, name);
|
groupDatabase.updateTitle(groupId, name);
|
||||||
@ -154,7 +154,7 @@ public class GroupManager {
|
|||||||
if (!GroupUtil.isMmsGroup(groupId)) {
|
if (!GroupUtil.isMmsGroup(groupId)) {
|
||||||
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes, adminAddresses);
|
return sendGroupUpdate(context, groupId, memberAddresses, name, avatarBytes, adminAddresses);
|
||||||
} else {
|
} else {
|
||||||
Recipient groupRecipient = Recipient.from(context, Address.Companion.fromSerialized(groupId), true);
|
Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), true);
|
||||||
long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient);
|
long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient);
|
||||||
return new GroupActionResult(groupRecipient, threadId);
|
return new GroupActionResult(groupRecipient, threadId);
|
||||||
}
|
}
|
||||||
@ -168,7 +168,7 @@ public class GroupManager {
|
|||||||
@NonNull Set<Address> admins)
|
@NonNull Set<Address> admins)
|
||||||
{
|
{
|
||||||
Attachment avatarAttachment = null;
|
Attachment avatarAttachment = null;
|
||||||
Address groupAddress = Address.Companion.fromSerialized(groupId);
|
Address groupAddress = Address.fromSerialized(groupId);
|
||||||
Recipient groupRecipient = Recipient.from(context, groupAddress, false);
|
Recipient groupRecipient = Recipient.from(context, groupAddress, false);
|
||||||
|
|
||||||
List<String> numbers = new LinkedList<>();
|
List<String> numbers = new LinkedList<>();
|
||||||
|
@ -18,7 +18,6 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
|
|||||||
import org.thoughtcrime.securesms.jobs.AvatarDownloadJob;
|
import org.thoughtcrime.securesms.jobs.AvatarDownloadJob;
|
||||||
import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob;
|
import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob;
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
|
|
||||||
import org.thoughtcrime.securesms.mms.MmsException;
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||||
import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
|
import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
|
||||||
@ -96,24 +95,20 @@ public class GroupMessageProcessor {
|
|||||||
|
|
||||||
if (group.getMembers().isPresent()) {
|
if (group.getMembers().isPresent()) {
|
||||||
for (String member : group.getMembers().get()) {
|
for (String member : group.getMembers().get()) {
|
||||||
members.add(Address.Companion.fromExternal(context, member));
|
members.add(Address.fromExternal(context, member));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loki - Parse admins
|
// Loki - Parse admins
|
||||||
if (group.getAdmins().isPresent()) {
|
if (group.getAdmins().isPresent()) {
|
||||||
for (String admin : group.getAdmins().get()) {
|
for (String admin : group.getAdmins().get()) {
|
||||||
admins.add(Address.Companion.fromExternal(context, admin));
|
admins.add(Address.fromExternal(context, admin));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
database.create(id, group.getName().orNull(), members,
|
database.create(id, group.getName().orNull(), members,
|
||||||
avatar != null && avatar.isPointer() ? avatar.asPointer() : null, null, admins, formationTimestamp);
|
avatar != null && avatar.isPointer() ? avatar.asPointer() : null, null, admins, formationTimestamp);
|
||||||
|
|
||||||
if (group.getMembers().isPresent()) {
|
|
||||||
ClosedGroupsProtocol.establishSessionsWithMembersIfNeeded(context, group.getMembers().get());
|
|
||||||
}
|
|
||||||
|
|
||||||
return storeMessage(context, content, group, builder.build(), outgoing);
|
return storeMessage(context, content, group, builder.build(), outgoing);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +122,7 @@ public class GroupMessageProcessor {
|
|||||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||||
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||||
String id = GroupUtil.getEncodedId(group);
|
String id = GroupUtil.getEncodedId(group);
|
||||||
Address address = Address.Companion.fromExternal(context, GroupUtil.getEncodedId(group));
|
Address address = Address.fromExternal(context, GroupUtil.getEncodedId(group));
|
||||||
Recipient recipient = Recipient.from(context, address, false);
|
Recipient recipient = Recipient.from(context, address, false);
|
||||||
|
|
||||||
String userMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
String userMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||||
@ -140,13 +135,13 @@ public class GroupMessageProcessor {
|
|||||||
|
|
||||||
if (group.getGroupType() == SignalServiceGroup.GroupType.SIGNAL) {
|
if (group.getGroupType() == SignalServiceGroup.GroupType.SIGNAL) {
|
||||||
// Loki - Only update the group if the group admin sent the message
|
// Loki - Only update the group if the group admin sent the message
|
||||||
if (!groupRecord.getAdmins().contains(Address.Companion.fromSerialized(content.getSender()))) {
|
if (!groupRecord.getAdmins().contains(Address.fromSerialized(content.getSender()))) {
|
||||||
Log.d("Loki", "Received a group update message from a non-admin user for: " + id +"; ignoring.");
|
Log.d("Loki", "Received a group update message from a non-admin user for: " + id +"; ignoring.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loki - Only process update messages if we're part of the group
|
// Loki - Only process update messages if we're part of the group
|
||||||
Address userMasterDeviceAddress = Address.Companion.fromSerialized(userMasterDevice);
|
Address userMasterDeviceAddress = Address.fromSerialized(userMasterDevice);
|
||||||
if (!groupRecord.getMembers().contains(userMasterDeviceAddress) &&
|
if (!groupRecord.getMembers().contains(userMasterDeviceAddress) &&
|
||||||
!group.getMembers().or(Collections.emptyList()).contains(userMasterDevice)) {
|
!group.getMembers().or(Collections.emptyList()).contains(userMasterDevice)) {
|
||||||
Log.d("Loki", "Received a group update message from a group we're not a member of: " + id + "; ignoring.");
|
Log.d("Loki", "Received a group update message from a group we're not a member of: " + id + "; ignoring.");
|
||||||
@ -159,7 +154,7 @@ public class GroupMessageProcessor {
|
|||||||
Set<Address> newMembers = new HashSet<>();
|
Set<Address> newMembers = new HashSet<>();
|
||||||
|
|
||||||
for (String messageMember : group.getMembers().get()) {
|
for (String messageMember : group.getMembers().get()) {
|
||||||
newMembers.add(Address.Companion.fromExternal(context, messageMember));
|
newMembers.add(Address.fromExternal(context, messageMember));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Added members are the members who are present in newMembers but not in currentMembers
|
// Added members are the members who are present in newMembers but not in currentMembers
|
||||||
@ -198,14 +193,10 @@ public class GroupMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we were removed then we need to disable the chat
|
// If we were removed then we need to disable the chat
|
||||||
if (removedMembers.contains(Address.Companion.fromSerialized(userMasterDevice))) {
|
if (removedMembers.contains(Address.fromSerialized(userMasterDevice))) {
|
||||||
database.setActive(id, false);
|
database.setActive(id, false);
|
||||||
} else {
|
} else {
|
||||||
if (!groupRecord.isActive()) database.setActive(id, true);
|
if (!groupRecord.isActive()) database.setActive(id, true);
|
||||||
|
|
||||||
if (group.getMembers().isPresent()) {
|
|
||||||
ClosedGroupsProtocol.establishSessionsWithMembersIfNeeded(context, group.getMembers().get());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return storeMessage(context, content, group, builder.build(), outgoing);
|
return storeMessage(context, content, group, builder.build(), outgoing);
|
||||||
@ -216,7 +207,7 @@ public class GroupMessageProcessor {
|
|||||||
@NonNull SignalServiceGroup group,
|
@NonNull SignalServiceGroup group,
|
||||||
@NonNull GroupRecord record)
|
@NonNull GroupRecord record)
|
||||||
{
|
{
|
||||||
if (record.getMembers().contains(Address.Companion.fromSerialized(content.getSender()))) {
|
if (record.getMembers().contains(Address.fromSerialized(content.getSender()))) {
|
||||||
ApplicationContext.getInstance(context)
|
ApplicationContext.getInstance(context)
|
||||||
.getJobManager()
|
.getJobManager()
|
||||||
.add(new PushGroupUpdateJob(content.getSender(), group.getGroupId()));
|
.add(new PushGroupUpdateJob(content.getSender(), group.getGroupId()));
|
||||||
@ -237,8 +228,8 @@ public class GroupMessageProcessor {
|
|||||||
GroupContext.Builder builder = createGroupContext(group);
|
GroupContext.Builder builder = createGroupContext(group);
|
||||||
builder.setType(GroupContext.Type.QUIT);
|
builder.setType(GroupContext.Type.QUIT);
|
||||||
|
|
||||||
if (members.contains(Address.Companion.fromExternal(context, content.getSender()))) {
|
if (members.contains(Address.fromExternal(context, content.getSender()))) {
|
||||||
database.removeMember(id, Address.Companion.fromExternal(context, content.getSender()));
|
database.removeMember(id, Address.fromExternal(context, content.getSender()));
|
||||||
if (outgoing) database.setActive(id, false);
|
if (outgoing) database.setActive(id, false);
|
||||||
|
|
||||||
return storeMessage(context, content, group, builder.build(), outgoing);
|
return storeMessage(context, content, group, builder.build(), outgoing);
|
||||||
@ -262,11 +253,11 @@ public class GroupMessageProcessor {
|
|||||||
try {
|
try {
|
||||||
if (outgoing) {
|
if (outgoing) {
|
||||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||||
Address address = Address.Companion.fromExternal(context, GroupUtil.getEncodedId(group));
|
Address address = Address.fromExternal(context, GroupUtil.getEncodedId(group));
|
||||||
Recipient recipient = Recipient.from(context, address, false);
|
Recipient recipient = Recipient.from(context, address, false);
|
||||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(recipient, storage, null, 0, null, Collections.emptyList(), Collections.emptyList());
|
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(recipient, storage, null, 0, null, Collections.emptyList(), Collections.emptyList());
|
||||||
long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
|
long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
|
||||||
Address senderAddress = Address.Companion.fromExternal(context, content.getSender());
|
Address senderAddress = Address.fromExternal(context, content.getSender());
|
||||||
MessageRecord existingMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(content.getTimestamp(), senderAddress);
|
MessageRecord existingMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(content.getTimestamp(), senderAddress);
|
||||||
long messageId;
|
long messageId;
|
||||||
if (existingMessage != null) {
|
if (existingMessage != null) {
|
||||||
@ -281,7 +272,7 @@ public class GroupMessageProcessor {
|
|||||||
} else {
|
} else {
|
||||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||||
String body = Base64.encodeBytes(storage.toByteArray());
|
String body = Base64.encodeBytes(storage.toByteArray());
|
||||||
IncomingTextMessage incoming = new IncomingTextMessage(Address.Companion.fromExternal(context, content.getSender()), content.getSenderDevice(), content.getTimestamp(), body, Optional.of(group), 0, content.isNeedsReceipt());
|
IncomingTextMessage incoming = new IncomingTextMessage(Address.fromExternal(context, content.getSender()), content.getSenderDevice(), content.getTimestamp(), body, Optional.of(group), 0, content.isNeedsReceipt());
|
||||||
IncomingGroupMessage groupMessage = new IncomingGroupMessage(incoming, storage, body);
|
IncomingGroupMessage groupMessage = new IncomingGroupMessage(incoming, storage, body);
|
||||||
|
|
||||||
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(groupMessage);
|
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(groupMessage);
|
||||||
|
@ -163,7 +163,7 @@ public class AttachmentUploadJob extends BaseJob implements InjectableType {
|
|||||||
public static final class Factory implements Job.Factory<AttachmentUploadJob> {
|
public static final class Factory implements Job.Factory<AttachmentUploadJob> {
|
||||||
@Override
|
@Override
|
||||||
public @NonNull AttachmentUploadJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
public @NonNull AttachmentUploadJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||||
return new AttachmentUploadJob(parameters, new AttachmentId(data.getLong(KEY_ROW_ID), data.getLong(KEY_UNIQUE_ID)), Address.Companion.fromSerialized(data.getString(KEY_DESTINATION)));
|
return new AttachmentUploadJob(parameters, new AttachmentId(data.getLong(KEY_ROW_ID), data.getLong(KEY_UNIQUE_ID)), Address.fromSerialized(data.getString(KEY_DESTINATION)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
|
|||||||
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
|
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
|
||||||
import org.thoughtcrime.securesms.loki.api.PrepareAttachmentAudioExtrasJob;
|
import org.thoughtcrime.securesms.loki.api.PrepareAttachmentAudioExtrasJob;
|
||||||
import org.thoughtcrime.securesms.loki.api.ResetThreadSessionJob;
|
import org.thoughtcrime.securesms.loki.api.ResetThreadSessionJob;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupUpdateMessageSendJob;
|
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupUpdateMessageSendJobV2;
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupUpdateMessageSendJobV2;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.NullMessageSendJob;
|
import org.thoughtcrime.securesms.loki.protocol.NullMessageSendJob;
|
||||||
|
|
||||||
@ -32,7 +31,6 @@ public final class JobManagerFactories {
|
|||||||
put(AttachmentDownloadJob.KEY, new AttachmentDownloadJob.Factory());
|
put(AttachmentDownloadJob.KEY, new AttachmentDownloadJob.Factory());
|
||||||
put(AttachmentUploadJob.KEY, new AttachmentUploadJob.Factory());
|
put(AttachmentUploadJob.KEY, new AttachmentUploadJob.Factory());
|
||||||
put(AvatarDownloadJob.KEY, new AvatarDownloadJob.Factory());
|
put(AvatarDownloadJob.KEY, new AvatarDownloadJob.Factory());
|
||||||
put(ClosedGroupUpdateMessageSendJob.KEY, new ClosedGroupUpdateMessageSendJob.Factory());
|
|
||||||
put(ClosedGroupUpdateMessageSendJobV2.KEY, new ClosedGroupUpdateMessageSendJobV2.Factory());
|
put(ClosedGroupUpdateMessageSendJobV2.KEY, new ClosedGroupUpdateMessageSendJobV2.Factory());
|
||||||
put(LocalBackupJob.KEY, new LocalBackupJob.Factory());
|
put(LocalBackupJob.KEY, new LocalBackupJob.Factory());
|
||||||
put(MmsDownloadJob.KEY, new MmsDownloadJob.Factory());
|
put(MmsDownloadJob.KEY, new MmsDownloadJob.Factory());
|
||||||
|
@ -206,7 +206,7 @@ public class MmsDownloadJob extends BaseJob {
|
|||||||
Address from;
|
Address from;
|
||||||
|
|
||||||
if (retrieved.getFrom() != null) {
|
if (retrieved.getFrom() != null) {
|
||||||
from = Address.Companion.fromExternal(context, Util.toIsoString(retrieved.getFrom().getTextString()));
|
from = Address.fromExternal(context, Util.toIsoString(retrieved.getFrom().getTextString()));
|
||||||
} else if (notificationFrom != null) {
|
} else if (notificationFrom != null) {
|
||||||
from = notificationFrom;
|
from = notificationFrom;
|
||||||
} else {
|
} else {
|
||||||
@ -215,18 +215,18 @@ public class MmsDownloadJob extends BaseJob {
|
|||||||
|
|
||||||
if (retrieved.getTo() != null) {
|
if (retrieved.getTo() != null) {
|
||||||
for (EncodedStringValue toValue : retrieved.getTo()) {
|
for (EncodedStringValue toValue : retrieved.getTo()) {
|
||||||
members.add(Address.Companion.fromExternal(context, Util.toIsoString(toValue.getTextString())));
|
members.add(Address.fromExternal(context, Util.toIsoString(toValue.getTextString())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retrieved.getCc() != null) {
|
if (retrieved.getCc() != null) {
|
||||||
for (EncodedStringValue ccValue : retrieved.getCc()) {
|
for (EncodedStringValue ccValue : retrieved.getCc()) {
|
||||||
members.add(Address.Companion.fromExternal(context, Util.toIsoString(ccValue.getTextString())));
|
members.add(Address.fromExternal(context, Util.toIsoString(ccValue.getTextString())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
members.add(from);
|
members.add(from);
|
||||||
members.add(Address.Companion.fromExternal(context, TextSecurePreferences.getLocalNumber(context)));
|
members.add(Address.fromExternal(context, TextSecurePreferences.getLocalNumber(context)));
|
||||||
|
|
||||||
if (retrieved.getBody() != null) {
|
if (retrieved.getBody() != null) {
|
||||||
body = PartParser.getMessageText(retrieved.getBody());
|
body = PartParser.getMessageText(retrieved.getBody());
|
||||||
@ -249,7 +249,7 @@ public class MmsDownloadJob extends BaseJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (members.size() > 2) {
|
if (members.size() > 2) {
|
||||||
group = Optional.of(Address.Companion.fromSerialized(DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(new LinkedList<>(members), new LinkedList<>())));
|
group = Optional.of(Address.fromSerialized(DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(new LinkedList<>(members), new LinkedList<>())));
|
||||||
}
|
}
|
||||||
|
|
||||||
IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false, false);
|
IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false, false);
|
||||||
|
@ -102,7 +102,7 @@ public class MmsReceiveJob extends BaseJob {
|
|||||||
|
|
||||||
private boolean isBlocked(GenericPdu pdu) {
|
private boolean isBlocked(GenericPdu pdu) {
|
||||||
if (pdu.getFrom() != null && pdu.getFrom().getTextString() != null) {
|
if (pdu.getFrom() != null && pdu.getFrom().getTextString() != null) {
|
||||||
Recipient recipients = Recipient.from(context, Address.Companion.fromExternal(context, Util.toIsoString(pdu.getFrom().getTextString())), false);
|
Recipient recipients = Recipient.from(context, Address.fromExternal(context, Util.toIsoString(pdu.getFrom().getTextString())), false);
|
||||||
return recipients.isBlocked();
|
return recipients.isBlocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,6 @@ import org.thoughtcrime.securesms.database.model.StickerRecord;
|
|||||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||||
import org.thoughtcrime.securesms.groups.GroupMessageProcessor;
|
import org.thoughtcrime.securesms.groups.GroupMessageProcessor;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
|
||||||
import org.thoughtcrime.securesms.linkpreview.Link;
|
import org.thoughtcrime.securesms.linkpreview.Link;
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
@ -77,7 +76,6 @@ import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl;
|
|||||||
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
|
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2;
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
||||||
@ -292,7 +290,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
SessionMetaProtocol.handleProfileKeyUpdate(context, content);
|
SessionMetaProtocol.handleProfileKeyUpdate(context, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SessionMetaProtocol.shouldSendDeliveryReceipt(message, Address.Companion.fromSerialized(content.getSender()))) {
|
if (SessionMetaProtocol.shouldSendDeliveryReceipt(message, Address.fromSerialized(content.getSender()))) {
|
||||||
handleNeedsDeliveryReceipt(content, message);
|
handleNeedsDeliveryReceipt(content, message);
|
||||||
}
|
}
|
||||||
} else if (content.getSyncMessage().isPresent()) {
|
} else if (content.getSyncMessage().isPresent()) {
|
||||||
@ -308,7 +306,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
Log.w(TAG, "Got unrecognized message...");
|
Log.w(TAG, "Got unrecognized message...");
|
||||||
}
|
}
|
||||||
|
|
||||||
resetRecipientToPush(Recipient.from(context, Address.Companion.fromSerialized(content.getSender()), false));
|
resetRecipientToPush(Recipient.from(context, Address.fromSerialized(content.getSender()), false));
|
||||||
|
|
||||||
// if (envelope.isPreKeySignalMessage()) {
|
// if (envelope.isPreKeySignalMessage()) {
|
||||||
// ApplicationContext.getInstance(context).getJobManager().add(new RefreshPreKeysJob());
|
// ApplicationContext.getInstance(context).getJobManager().add(new RefreshPreKeysJob());
|
||||||
@ -351,7 +349,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
@NonNull Optional<Long> smsMessageId)
|
@NonNull Optional<Long> smsMessageId)
|
||||||
{
|
{
|
||||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||||
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(Address.Companion.fromSerialized(content.getSender()),
|
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(Address.fromSerialized(content.getSender()),
|
||||||
content.getSenderDevice(),
|
content.getSenderDevice(),
|
||||||
content.getTimestamp(),
|
content.getTimestamp(),
|
||||||
"", Optional.absent(), 0,
|
"", Optional.absent(), 0,
|
||||||
@ -462,7 +460,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
if (syncTarget != null && !syncTarget.isEmpty() || TextSecurePreferences.getLocalNumber(context).equals(content.getSender())) {
|
if (syncTarget != null && !syncTarget.isEmpty() || TextSecurePreferences.getLocalNumber(context).equals(content.getSender())) {
|
||||||
Address targetAddress = masterRecipient.getAddress();
|
Address targetAddress = masterRecipient.getAddress();
|
||||||
if (message.getGroupInfo().isPresent()) {
|
if (message.getGroupInfo().isPresent()) {
|
||||||
targetAddress = Address.Companion.fromSerialized(GroupUtil.getEncodedId(message.getGroupInfo().get()));
|
targetAddress = Address.fromSerialized(GroupUtil.getEncodedId(message.getGroupInfo().get()));
|
||||||
} else if (syncTarget != null && !syncTarget.isEmpty()) {
|
} else if (syncTarget != null && !syncTarget.isEmpty()) {
|
||||||
targetAddress = Address.fromSerialized(syncTarget);
|
targetAddress = Address.fromSerialized(syncTarget);
|
||||||
}
|
}
|
||||||
@ -723,7 +721,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
} else if (syncTarget != null && !syncTarget.isEmpty() || TextSecurePreferences.getLocalNumber(context).equals(content.getSender())) {
|
} else if (syncTarget != null && !syncTarget.isEmpty() || TextSecurePreferences.getLocalNumber(context).equals(content.getSender())) {
|
||||||
Address targetAddress = masterRecipient.getAddress();
|
Address targetAddress = masterRecipient.getAddress();
|
||||||
if (message.getGroupInfo().isPresent()) {
|
if (message.getGroupInfo().isPresent()) {
|
||||||
targetAddress = Address.Companion.fromSerialized(GroupUtil.getEncodedId(message.getGroupInfo().get()));
|
targetAddress = Address.fromSerialized(GroupUtil.getEncodedId(message.getGroupInfo().get()));
|
||||||
} else if (syncTarget != null && !syncTarget.isEmpty()) {
|
} else if (syncTarget != null && !syncTarget.isEmpty()) {
|
||||||
targetAddress = Address.fromSerialized(syncTarget);
|
targetAddress = Address.fromSerialized(syncTarget);
|
||||||
}
|
}
|
||||||
@ -924,7 +922,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (canRecoverAutomatically(e)) {
|
if (canRecoverAutomatically(e)) {
|
||||||
Recipient recipient = Recipient.from(context, Address.Companion.fromSerialized(sender), false);
|
Recipient recipient = Recipient.from(context, Address.fromSerialized(sender), false);
|
||||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context);
|
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context);
|
||||||
long threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
|
long threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
|
||||||
threadDB.addSessionRestoreDevice(threadID, sender);
|
threadDB.addSessionRestoreDevice(threadID, sender);
|
||||||
@ -965,9 +963,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
smsDatabase.markAsNoSession(smsMessageId.get());
|
smsDatabase.markAsNoSession(smsMessageId.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to recover automatically
|
|
||||||
ApplicationContext.getInstance(context).sendSessionRequestIfNeeded(sender);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleLegacyMessage(@NonNull String sender, int senderDevice, long timestamp,
|
private void handleLegacyMessage(@NonNull String sender, int senderDevice, long timestamp,
|
||||||
@ -1008,7 +1003,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
{
|
{
|
||||||
ApplicationContext.getInstance(context)
|
ApplicationContext.getInstance(context)
|
||||||
.getJobManager()
|
.getJobManager()
|
||||||
.add(new SendDeliveryReceiptJob(Address.Companion.fromSerialized(content.getSender()), message.getTimestamp()));
|
.add(new SendDeliveryReceiptJob(Address.fromSerialized(content.getSender()), message.getTimestamp()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
@ -1016,7 +1011,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
@NonNull SignalServiceReceiptMessage message)
|
@NonNull SignalServiceReceiptMessage message)
|
||||||
{
|
{
|
||||||
// Redirect message to master device conversation
|
// Redirect message to master device conversation
|
||||||
Address masterAddress = Address.Companion.fromSerialized(content.getSender());
|
Address masterAddress = Address.fromSerialized(content.getSender());
|
||||||
|
|
||||||
if (masterAddress.isContact()) {
|
if (masterAddress.isContact()) {
|
||||||
Recipient masterRecipient = getMessageMasterDestination(content.getSender());
|
Recipient masterRecipient = getMessageMasterDestination(content.getSender());
|
||||||
@ -1037,7 +1032,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
if (TextSecurePreferences.isReadReceiptsEnabled(context)) {
|
if (TextSecurePreferences.isReadReceiptsEnabled(context)) {
|
||||||
|
|
||||||
// Redirect message to master device conversation
|
// Redirect message to master device conversation
|
||||||
Address masterAddress = Address.Companion.fromSerialized(content.getSender());
|
Address masterAddress = Address.fromSerialized(content.getSender());
|
||||||
|
|
||||||
if (masterAddress.isContact()) {
|
if (masterAddress.isContact()) {
|
||||||
Recipient masterRecipient = getMessageMasterDestination(content.getSender());
|
Recipient masterRecipient = getMessageMasterDestination(content.getSender());
|
||||||
@ -1060,13 +1055,13 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Recipient author = Recipient.from(context, Address.Companion.fromSerialized(content.getSender()), false);
|
Recipient author = Recipient.from(context, Address.fromSerialized(content.getSender()), false);
|
||||||
|
|
||||||
long threadId;
|
long threadId;
|
||||||
|
|
||||||
if (typingMessage.getGroupId().isPresent()) {
|
if (typingMessage.getGroupId().isPresent()) {
|
||||||
// Typing messages should only apply to closed groups, thus we use `getEncodedId`
|
// Typing messages should only apply to closed groups, thus we use `getEncodedId`
|
||||||
Address groupAddress = Address.Companion.fromSerialized(GroupUtil.getEncodedClosedGroupID(typingMessage.getGroupId().get()));
|
Address groupAddress = Address.fromSerialized(GroupUtil.getEncodedClosedGroupID(typingMessage.getGroupId().get()));
|
||||||
Recipient groupRecipient = Recipient.from(context, groupAddress, false);
|
Recipient groupRecipient = Recipient.from(context, groupAddress, false);
|
||||||
|
|
||||||
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(groupRecipient);
|
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(groupRecipient);
|
||||||
@ -1103,7 +1098,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
}
|
}
|
||||||
|
|
||||||
Address author = Address.Companion.fromSerialized(quote.get().getAuthor().getNumber());
|
Address author = Address.fromSerialized(quote.get().getAuthor().getNumber());
|
||||||
MessageRecord message = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(quote.get().getId(), author);
|
MessageRecord message = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(quote.get().getId(), author);
|
||||||
|
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
@ -1218,49 +1213,49 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
|
|
||||||
private Recipient getSyncMessageDestination(SentTranscriptMessage message) {
|
private Recipient getSyncMessageDestination(SentTranscriptMessage message) {
|
||||||
if (message.getMessage().isGroupMessage()) {
|
if (message.getMessage().isGroupMessage()) {
|
||||||
return Recipient.from(context, Address.Companion.fromSerialized(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get())), false);
|
return Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get())), false);
|
||||||
} else {
|
} else {
|
||||||
return Recipient.from(context, Address.Companion.fromSerialized(message.getDestination().get()), false);
|
return Recipient.from(context, Address.fromSerialized(message.getDestination().get()), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Recipient getSyncMessageMasterDestination(SentTranscriptMessage message) {
|
private Recipient getSyncMessageMasterDestination(SentTranscriptMessage message) {
|
||||||
if (message.getMessage().isGroupMessage()) {
|
if (message.getMessage().isGroupMessage()) {
|
||||||
return Recipient.from(context, Address.Companion.fromSerialized(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get())), false);
|
return Recipient.from(context, Address.fromSerialized(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get())), false);
|
||||||
} else {
|
} else {
|
||||||
String publicKey = message.getDestination().get();
|
String publicKey = message.getDestination().get();
|
||||||
String userPublicKey = TextSecurePreferences.getLocalNumber(context);
|
String userPublicKey = TextSecurePreferences.getLocalNumber(context);
|
||||||
if (publicKey.equals(userPublicKey)) {
|
if (publicKey.equals(userPublicKey)) {
|
||||||
return Recipient.from(context, Address.Companion.fromSerialized(userPublicKey), false);
|
return Recipient.from(context, Address.fromSerialized(userPublicKey), false);
|
||||||
} else {
|
} else {
|
||||||
return Recipient.from(context, Address.Companion.fromSerialized(publicKey), false);
|
return Recipient.from(context, Address.fromSerialized(publicKey), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Recipient getMessageDestination(SignalServiceContent content, SignalServiceDataMessage message) {
|
private Recipient getMessageDestination(SignalServiceContent content, SignalServiceDataMessage message) {
|
||||||
if (message.getGroupInfo().isPresent()) {
|
if (message.getGroupInfo().isPresent()) {
|
||||||
return Recipient.from(context, Address.Companion.fromExternal(context, GroupUtil.getEncodedClosedGroupID(message.getGroupInfo().get().getGroupId())), false);
|
return Recipient.from(context, Address.fromExternal(context, GroupUtil.getEncodedClosedGroupID(message.getGroupInfo().get().getGroupId())), false);
|
||||||
} else {
|
} else {
|
||||||
return Recipient.from(context, Address.Companion.fromExternal(context, content.getSender()), false);
|
return Recipient.from(context, Address.fromExternal(context, content.getSender()), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Recipient getMessageMasterDestination(String publicKey) {
|
private Recipient getMessageMasterDestination(String publicKey) {
|
||||||
if (!PublicKeyValidation.isValid(publicKey)) {
|
if (!PublicKeyValidation.isValid(publicKey)) {
|
||||||
return Recipient.from(context, Address.Companion.fromSerialized(publicKey), false);
|
return Recipient.from(context, Address.fromSerialized(publicKey), false);
|
||||||
} else {
|
} else {
|
||||||
String userPublicKey = TextSecurePreferences.getLocalNumber(context);
|
String userPublicKey = TextSecurePreferences.getLocalNumber(context);
|
||||||
if (publicKey.equals(userPublicKey)) {
|
if (publicKey.equals(userPublicKey)) {
|
||||||
return Recipient.from(context, Address.Companion.fromSerialized(userPublicKey), false);
|
return Recipient.from(context, Address.fromSerialized(userPublicKey), false);
|
||||||
} else {
|
} else {
|
||||||
return Recipient.from(context, Address.Companion.fromSerialized(publicKey), false);
|
return Recipient.from(context, Address.fromSerialized(publicKey), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyTypingStoppedFromIncomingMessage(@NonNull Recipient conversationRecipient, @NonNull String sender, int device) {
|
private void notifyTypingStoppedFromIncomingMessage(@NonNull Recipient conversationRecipient, @NonNull String sender, int device) {
|
||||||
Recipient author = Recipient.from(context, Address.Companion.fromSerialized(sender), false);
|
Recipient author = Recipient.from(context, Address.fromSerialized(sender), false);
|
||||||
long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(conversationRecipient);
|
long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(conversationRecipient);
|
||||||
|
|
||||||
if (threadId > 0) {
|
if (threadId > 0) {
|
||||||
@ -1286,7 +1281,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Recipient sender = Recipient.from(context, Address.Companion.fromSerialized(content.getSender()), false);
|
Recipient sender = Recipient.from(context, Address.fromSerialized(content.getSender()), false);
|
||||||
|
|
||||||
if (content.getDataMessage().isPresent()) {
|
if (content.getDataMessage().isPresent()) {
|
||||||
SignalServiceDataMessage message = content.getDataMessage().get();
|
SignalServiceDataMessage message = content.getDataMessage().get();
|
||||||
@ -1310,8 +1305,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
boolean isGroupActive = groupId.isPresent() && groupDatabase.isActive(groupId.get());
|
boolean isGroupActive = groupId.isPresent() && groupDatabase.isActive(groupId.get());
|
||||||
boolean isLeaveMessage = message.getGroupInfo().isPresent() && message.getGroupInfo().get().getType() == SignalServiceGroup.Type.QUIT;
|
boolean isLeaveMessage = message.getGroupInfo().isPresent() && message.getGroupInfo().get().getType() == SignalServiceGroup.Type.QUIT;
|
||||||
|
|
||||||
boolean shouldIgnoreContentMessage = ClosedGroupsProtocol.shouldIgnoreContentMessage(context, conversation.getAddress(), groupId.orNull(), content.getSender());
|
return (isContentMessage && !isGroupActive) || (sender.isBlocked() && !isLeaveMessage);
|
||||||
return (isContentMessage && !isGroupActive) || (sender.isBlocked() && !isLeaveMessage) || (isContentMessage && shouldIgnoreContentMessage);
|
|
||||||
} else {
|
} else {
|
||||||
return sender.isBlocked();
|
return sender.isBlocked();
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ import org.thoughtcrime.securesms.jobmanager.Job;
|
|||||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||||
import org.session.libsignal.utilities.logging.Log;
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol;
|
|
||||||
import org.thoughtcrime.securesms.mms.MmsException;
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
@ -157,14 +156,14 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
|||||||
|
|
||||||
List<Address> targets;
|
List<Address> targets;
|
||||||
|
|
||||||
if (filterAddress != null) targets = Collections.singletonList(Address.Companion.fromSerialized(filterAddress));
|
if (filterAddress != null) targets = Collections.singletonList(Address.fromSerialized(filterAddress));
|
||||||
else if (!existingNetworkFailures.isEmpty()) targets = Stream.of(existingNetworkFailures).map(NetworkFailure::getAddress).toList();
|
else if (!existingNetworkFailures.isEmpty()) targets = Stream.of(existingNetworkFailures).map(NetworkFailure::getAddress).toList();
|
||||||
else targets = ClosedGroupsProtocol.getMessageDestinations(context, message.getRecipient().getAddress().toGroupString());
|
else targets = Collections.singletonList(Address.fromSerialized(message.getRecipient().getAddress().toGroupString()));
|
||||||
|
|
||||||
List<SendMessageResult> results = deliver(message, targets);
|
List<SendMessageResult> results = deliver(message, targets);
|
||||||
List<NetworkFailure> networkFailures = Stream.of(results).filter(SendMessageResult::isNetworkFailure).map(result -> new NetworkFailure(Address.Companion.fromSerialized(result.getAddress().getNumber()))).toList();
|
List<NetworkFailure> networkFailures = Stream.of(results).filter(SendMessageResult::isNetworkFailure).map(result -> new NetworkFailure(Address.fromSerialized(result.getAddress().getNumber()))).toList();
|
||||||
List<IdentityKeyMismatch> identityMismatches = Stream.of(results).filter(result -> result.getIdentityFailure() != null).map(result -> new IdentityKeyMismatch(Address.Companion.fromSerialized(result.getAddress().getNumber()), result.getIdentityFailure().getIdentityKey())).toList();
|
List<IdentityKeyMismatch> identityMismatches = Stream.of(results).filter(result -> result.getIdentityFailure() != null).map(result -> new IdentityKeyMismatch(Address.fromSerialized(result.getAddress().getNumber()), result.getIdentityFailure().getIdentityKey())).toList();
|
||||||
Set<Address> successAddresses = Stream.of(results).filter(result -> result.getSuccess() != null).map(result -> Address.Companion.fromSerialized(result.getAddress().getNumber())).collect(Collectors.toSet());
|
Set<Address> successAddresses = Stream.of(results).filter(result -> result.getSuccess() != null).map(result -> Address.fromSerialized(result.getAddress().getNumber())).collect(Collectors.toSet());
|
||||||
List<NetworkFailure> resolvedNetworkFailures = Stream.of(existingNetworkFailures).filter(failure -> successAddresses.contains(failure.getAddress())).toList();
|
List<NetworkFailure> resolvedNetworkFailures = Stream.of(existingNetworkFailures).filter(failure -> successAddresses.contains(failure.getAddress())).toList();
|
||||||
List<IdentityKeyMismatch> resolvedIdentityFailures = Stream.of(existingIdentityMismatches).filter(failure -> successAddresses.contains(failure.getAddress())).toList();
|
List<IdentityKeyMismatch> resolvedIdentityFailures = Stream.of(existingIdentityMismatches).filter(failure -> successAddresses.contains(failure.getAddress())).toList();
|
||||||
List<SendMessageResult> successes = Stream.of(results).filter(result -> result.getSuccess() != null).toList();
|
List<SendMessageResult> successes = Stream.of(results).filter(result -> result.getSuccess() != null).toList();
|
||||||
@ -188,7 +187,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (SendMessageResult success : successes) {
|
for (SendMessageResult success : successes) {
|
||||||
DatabaseFactory.getGroupReceiptDatabase(context).setUnidentified(Address.Companion.fromSerialized(success.getAddress().getNumber()),
|
DatabaseFactory.getGroupReceiptDatabase(context).setUnidentified(Address.fromSerialized(success.getAddress().getNumber()),
|
||||||
messageId,
|
messageId,
|
||||||
success.getSuccess().isUnidentified());
|
success.getSuccess().isUnidentified());
|
||||||
}
|
}
|
||||||
@ -232,19 +231,11 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
|||||||
private List<SendMessageResult> deliver(OutgoingMediaMessage message, @NonNull List<Address> destinations)
|
private List<SendMessageResult> deliver(OutgoingMediaMessage message, @NonNull List<Address> destinations)
|
||||||
throws IOException, UntrustedIdentityException, UndeliverableMessageException {
|
throws IOException, UntrustedIdentityException, UndeliverableMessageException {
|
||||||
|
|
||||||
// Loki - The user shouldn't be able to message RSS feeds
|
|
||||||
Address address = message.getRecipient().getAddress();
|
Address address = message.getRecipient().getAddress();
|
||||||
// if (address.isRSSFeed()) {
|
|
||||||
// List<SendMessageResult> results = new ArrayList<>();
|
|
||||||
// for (Address destination : destinations) {
|
|
||||||
// results.add(SendMessageResult.networkFailure(new SignalServiceAddress(destination.toPhoneString())));
|
|
||||||
// }
|
|
||||||
// return results;
|
|
||||||
// }
|
|
||||||
|
|
||||||
List<SignalServiceAddress> addresses = Stream.of(destinations).map(this::getPushAddress).toList();
|
List<SignalServiceAddress> addresses = Stream.of(destinations).map(this::getPushAddress).toList();
|
||||||
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(addresses)
|
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(addresses)
|
||||||
.map(a -> Address.Companion.fromSerialized(a.getNumber()))
|
.map(a -> Address.fromSerialized(a.getNumber()))
|
||||||
.map(a -> Recipient.from(context, a, false))
|
.map(a -> Recipient.from(context, a, false))
|
||||||
.map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient))
|
.map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient))
|
||||||
.toList();
|
.toList();
|
||||||
@ -306,7 +297,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
|||||||
@Override
|
@Override
|
||||||
public @NonNull PushGroupSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
public @NonNull PushGroupSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||||
String address = data.getString(KEY_FILTER_ADDRESS);
|
String address = data.getString(KEY_FILTER_ADDRESS);
|
||||||
Address filter = address != null ? Address.Companion.fromSerialized(data.getString(KEY_FILTER_ADDRESS)) : null;
|
Address filter = address != null ? Address.fromSerialized(data.getString(KEY_FILTER_ADDRESS)) : null;
|
||||||
|
|
||||||
return new PushGroupSendJob(parameters, data.getLong(KEY_MESSAGE_ID), filter);
|
return new PushGroupSendJob(parameters, data.getLong(KEY_MESSAGE_ID), filter);
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ public class PushGroupUpdateJob extends BaseJob implements InjectableType {
|
|||||||
.withName(record.get().getTitle())
|
.withName(record.get().getTitle())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Address groupAddress = Address.Companion.fromSerialized(GroupUtil.getEncodedClosedGroupID(groupId));
|
Address groupAddress = Address.fromSerialized(GroupUtil.getEncodedClosedGroupID(groupId));
|
||||||
Recipient groupRecipient = Recipient.from(context, groupAddress, false);
|
Recipient groupRecipient = Recipient.from(context, groupAddress, false);
|
||||||
|
|
||||||
SignalServiceDataMessage message = SignalServiceDataMessage.newBuilder()
|
SignalServiceDataMessage message = SignalServiceDataMessage.newBuilder()
|
||||||
@ -126,7 +126,7 @@ public class PushGroupUpdateJob extends BaseJob implements InjectableType {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
messageSender.sendMessage(0, new SignalServiceAddress(source),
|
messageSender.sendMessage(0, new SignalServiceAddress(source),
|
||||||
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.Companion.fromSerialized(source), false)),
|
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(source), false)),
|
||||||
message);
|
message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
|||||||
} catch (UntrustedIdentityException uie) {
|
} catch (UntrustedIdentityException uie) {
|
||||||
warn(TAG, "Failure", uie);
|
warn(TAG, "Failure", uie);
|
||||||
if (messageId >= 0) {
|
if (messageId >= 0) {
|
||||||
database.addMismatchedIdentity(messageId, Address.Companion.fromSerialized(uie.getE164Number()), uie.getIdentityKey());
|
database.addMismatchedIdentity(messageId, Address.fromSerialized(uie.getE164Number()), uie.getIdentityKey());
|
||||||
database.markAsSentFailed(messageId);
|
database.markAsSentFailed(messageId);
|
||||||
}
|
}
|
||||||
} catch (SnodeAPI.Error e) {
|
} catch (SnodeAPI.Error e) {
|
||||||
@ -331,7 +331,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
|||||||
public @NonNull PushMediaSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
public @NonNull PushMediaSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||||
long templateMessageID = data.getLong(KEY_TEMPLATE_MESSAGE_ID);
|
long templateMessageID = data.getLong(KEY_TEMPLATE_MESSAGE_ID);
|
||||||
long messageID = data.getLong(KEY_MESSAGE_ID);
|
long messageID = data.getLong(KEY_MESSAGE_ID);
|
||||||
Address destination = Address.Companion.fromSerialized(data.getString(KEY_DESTINATION));
|
Address destination = Address.fromSerialized(data.getString(KEY_DESTINATION));
|
||||||
return new PushMediaSendJob(parameters, templateMessageID, messageID, destination);
|
return new PushMediaSendJob(parameters, templateMessageID, messageID, destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ public abstract class PushReceivedJob extends BaseJob {
|
|||||||
synchronized (RECEIVE_LOCK) {
|
synchronized (RECEIVE_LOCK) {
|
||||||
try {
|
try {
|
||||||
if (envelope.hasSource()) {
|
if (envelope.hasSource()) {
|
||||||
Address source = Address.Companion.fromExternal(context, envelope.getSource());
|
Address source = Address.fromExternal(context, envelope.getSource());
|
||||||
Recipient recipient = Recipient.from(context, source, false);
|
Recipient recipient = Recipient.from(context, source, false);
|
||||||
|
|
||||||
if (!isActiveNumber(recipient)) {
|
if (!isActiveNumber(recipient)) {
|
||||||
@ -54,7 +54,7 @@ public abstract class PushReceivedJob extends BaseJob {
|
|||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
private void handleReceipt(SignalServiceEnvelope envelope) {
|
private void handleReceipt(SignalServiceEnvelope envelope) {
|
||||||
Log.i(TAG, String.format("Received receipt: (XXXXX, %d)", envelope.getTimestamp()));
|
Log.i(TAG, String.format("Received receipt: (XXXXX, %d)", envelope.getTimestamp()));
|
||||||
DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(new SyncMessageId(Address.Companion.fromExternal(context, envelope.getSource()),
|
DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()),
|
||||||
envelope.getTimestamp()), System.currentTimeMillis());
|
envelope.getTimestamp()), System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
|||||||
} catch (UntrustedIdentityException e) {
|
} catch (UntrustedIdentityException e) {
|
||||||
warn(TAG, "Couldn't send message due to error: ", e);
|
warn(TAG, "Couldn't send message due to error: ", e);
|
||||||
if (messageId >= 0) {
|
if (messageId >= 0) {
|
||||||
database.addMismatchedIdentity(record.getId(), Address.Companion.fromSerialized(e.getE164Number()), e.getIdentityKey());
|
database.addMismatchedIdentity(record.getId(), Address.fromSerialized(e.getE164Number()), e.getIdentityKey());
|
||||||
database.markAsSentFailed(record.getId());
|
database.markAsSentFailed(record.getId());
|
||||||
database.markAsPush(record.getId());
|
database.markAsPush(record.getId());
|
||||||
}
|
}
|
||||||
@ -266,7 +266,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
|||||||
public @NonNull PushTextSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
public @NonNull PushTextSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||||
long templateMessageID = data.getLong(KEY_TEMPLATE_MESSAGE_ID);
|
long templateMessageID = data.getLong(KEY_TEMPLATE_MESSAGE_ID);
|
||||||
long messageID = data.getLong(KEY_MESSAGE_ID);
|
long messageID = data.getLong(KEY_MESSAGE_ID);
|
||||||
Address destination = Address.Companion.fromSerialized(data.getString(KEY_DESTINATION));
|
Address destination = Address.fromSerialized(data.getString(KEY_DESTINATION));
|
||||||
return new PushTextSendJob(parameters, templateMessageID, messageID, destination);
|
return new PushTextSendJob(parameters, templateMessageID, messageID, destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ public class RequestGroupInfoJob extends BaseJob implements InjectableType {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
messageSender.sendMessage(0, new SignalServiceAddress(source),
|
messageSender.sendMessage(0, new SignalServiceAddress(source),
|
||||||
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.Companion.fromExternal(context, source), false)),
|
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromExternal(context, source), false)),
|
||||||
message);
|
message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ public class RetrieveProfileAvatarJob extends BaseJob implements InjectableType
|
|||||||
@Override
|
@Override
|
||||||
public @NonNull RetrieveProfileAvatarJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
public @NonNull RetrieveProfileAvatarJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||||
return new RetrieveProfileAvatarJob(parameters,
|
return new RetrieveProfileAvatarJob(parameters,
|
||||||
Recipient.from(application, Address.Companion.fromSerialized(data.getString(KEY_ADDRESS)), true),
|
Recipient.from(application, Address.fromSerialized(data.getString(KEY_ADDRESS)), true),
|
||||||
data.getString(KEY_PROFILE_AVATAR));
|
data.getString(KEY_PROFILE_AVATAR));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ public class SendDeliveryReceiptJob extends BaseJob implements InjectableType {
|
|||||||
timestamp);
|
timestamp);
|
||||||
|
|
||||||
messageSender.sendReceipt(remoteAddress,
|
messageSender.sendReceipt(remoteAddress,
|
||||||
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.Companion.fromSerialized(address), false)),
|
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(address), false)),
|
||||||
receiptMessage);
|
receiptMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ public class SendDeliveryReceiptJob extends BaseJob implements InjectableType {
|
|||||||
@Override
|
@Override
|
||||||
public @NonNull SendDeliveryReceiptJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
public @NonNull SendDeliveryReceiptJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||||
return new SendDeliveryReceiptJob(parameters,
|
return new SendDeliveryReceiptJob(parameters,
|
||||||
Address.Companion.fromSerialized(data.getString(KEY_ADDRESS)),
|
Address.fromSerialized(data.getString(KEY_ADDRESS)),
|
||||||
data.getLong(KEY_MESSAGE_ID),
|
data.getLong(KEY_MESSAGE_ID),
|
||||||
data.getLong(KEY_TIMESTAMP));
|
data.getLong(KEY_TIMESTAMP));
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ public class SendReadReceiptJob extends BaseJob implements InjectableType {
|
|||||||
SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.READ, messageIds, timestamp);
|
SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.READ, messageIds, timestamp);
|
||||||
|
|
||||||
messageSender.sendReceipt(remoteAddress,
|
messageSender.sendReceipt(remoteAddress,
|
||||||
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.Companion.fromSerialized(address), false)),
|
UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(address), false)),
|
||||||
receiptMessage);
|
receiptMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ public class SendReadReceiptJob extends BaseJob implements InjectableType {
|
|||||||
public static final class Factory implements Job.Factory<SendReadReceiptJob> {
|
public static final class Factory implements Job.Factory<SendReadReceiptJob> {
|
||||||
@Override
|
@Override
|
||||||
public @NonNull SendReadReceiptJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
public @NonNull SendReadReceiptJob create(@NonNull Parameters parameters, @NonNull Data data) {
|
||||||
Address address = Address.Companion.fromSerialized(data.getString(KEY_ADDRESS));
|
Address address = Address.fromSerialized(data.getString(KEY_ADDRESS));
|
||||||
long timestamp = data.getLong(KEY_TIMESTAMP);
|
long timestamp = data.getLong(KEY_TIMESTAMP);
|
||||||
long[] ids = data.hasLongArray(KEY_MESSAGE_IDS) ? data.getLongArray(KEY_MESSAGE_IDS) : new long[0];
|
long[] ids = data.hasLongArray(KEY_MESSAGE_IDS) ? data.getLongArray(KEY_MESSAGE_IDS) : new long[0];
|
||||||
List<Long> messageIds = new ArrayList<>(ids.length);
|
List<Long> messageIds = new ArrayList<>(ids.length);
|
||||||
|
@ -19,20 +19,20 @@ import nl.komponents.kovenant.Promise
|
|||||||
import nl.komponents.kovenant.task
|
import nl.komponents.kovenant.task
|
||||||
import nl.komponents.kovenant.ui.failUi
|
import nl.komponents.kovenant.ui.failUi
|
||||||
import nl.komponents.kovenant.ui.successUi
|
import nl.komponents.kovenant.ui.successUi
|
||||||
import org.session.libsignal.service.loki.utilities.toHexString
|
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.session.libsession.messaging.threads.Address
|
import org.session.libsession.messaging.threads.Address
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.groups.GroupManager
|
import org.thoughtcrime.securesms.groups.GroupManager
|
||||||
import org.thoughtcrime.securesms.loki.dialogs.ClosedGroupEditingOptionsBottomSheet
|
import org.thoughtcrime.securesms.loki.dialogs.ClosedGroupEditingOptionsBottomSheet
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol
|
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2
|
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2
|
||||||
import org.thoughtcrime.securesms.loki.utilities.fadeIn
|
import org.thoughtcrime.securesms.loki.utilities.fadeIn
|
||||||
import org.thoughtcrime.securesms.loki.utilities.fadeOut
|
import org.thoughtcrime.securesms.loki.utilities.fadeOut
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import org.thoughtcrime.securesms.mms.GlideApp
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||||
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsession.utilities.ThemeUtil
|
import org.session.libsession.utilities.ThemeUtil
|
||||||
|
import org.session.libsignal.service.loki.utilities.toHexString
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
||||||
@ -249,7 +249,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
var isSSKBasedClosedGroup: Boolean
|
var isSSKBasedClosedGroup: Boolean
|
||||||
var groupPublicKey: String?
|
var groupPublicKey: String?
|
||||||
try {
|
try {
|
||||||
groupPublicKey = ClosedGroupsProtocol.doubleDecodeGroupID(groupID).toHexString()
|
groupPublicKey = GroupUtil.doubleDecodeGroupID(groupID).toHexString()
|
||||||
isSSKBasedClosedGroup = DatabaseFactory.getSSKDatabase(this).isSSKBasedClosedGroup(groupPublicKey)
|
isSSKBasedClosedGroup = DatabaseFactory.getSSKDatabase(this).isSSKBasedClosedGroup(groupPublicKey)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
groupPublicKey = null
|
groupPublicKey = null
|
||||||
@ -299,7 +299,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
isLoading = false
|
isLoading = false
|
||||||
finish()
|
finish()
|
||||||
}.failUi { exception ->
|
}.failUi { exception ->
|
||||||
val message = if (exception is ClosedGroupsProtocol.Error) exception.description else "An error occurred"
|
val message = if (exception is ClosedGroupsProtocolV2.Error) exception.description else "An error occurred"
|
||||||
Toast.makeText(this@EditClosedGroupActivity, message, Toast.LENGTH_LONG).show()
|
Toast.makeText(this@EditClosedGroupActivity, message, Toast.LENGTH_LONG).show()
|
||||||
loader.fadeOut()
|
loader.fadeOut()
|
||||||
isLoading = false
|
isLoading = false
|
||||||
|
@ -29,10 +29,10 @@ import org.thoughtcrime.securesms.ApplicationContext
|
|||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
||||||
import org.session.libsession.messaging.threads.Address
|
import org.session.libsession.messaging.threads.Address
|
||||||
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
import org.thoughtcrime.securesms.loki.api.ResetThreadSessionJob
|
import org.thoughtcrime.securesms.loki.api.ResetThreadSessionJob
|
||||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol
|
|
||||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
|
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
|
||||||
import org.thoughtcrime.securesms.loki.utilities.*
|
import org.thoughtcrime.securesms.loki.utilities.*
|
||||||
import org.thoughtcrime.securesms.loki.views.ConversationView
|
import org.thoughtcrime.securesms.loki.views.ConversationView
|
||||||
@ -46,7 +46,6 @@ import org.session.libsession.utilities.TextSecurePreferences.setBooleanPreferen
|
|||||||
import org.session.libsession.utilities.Util
|
import org.session.libsession.utilities.Util
|
||||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager
|
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager
|
||||||
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol
|
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol
|
||||||
import org.session.libsignal.service.loki.protocol.sessionmanagement.SessionManagementProtocol
|
|
||||||
import org.session.libsignal.utilities.ThreadUtils
|
import org.session.libsignal.utilities.ThreadUtils
|
||||||
import org.session.libsignal.service.loki.utilities.toHexString
|
import org.session.libsignal.service.loki.utilities.toHexString
|
||||||
import org.thoughtcrime.securesms.loki.dialogs.*
|
import org.thoughtcrime.securesms.loki.dialogs.*
|
||||||
@ -176,7 +175,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
|||||||
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||||
application.publicChatManager.startPollersIfNeeded()
|
application.publicChatManager.startPollersIfNeeded()
|
||||||
}
|
}
|
||||||
SessionManagementProtocol.configureIfNeeded(sessionResetImpl, sskDatabase, application)
|
|
||||||
IP2Country.configureIfNeeded(this)
|
IP2Country.configureIfNeeded(this)
|
||||||
application.registerForFCMIfNeeded(false)
|
application.registerForFCMIfNeeded(false)
|
||||||
// Observe blocked contacts changed events
|
// Observe blocked contacts changed events
|
||||||
@ -339,7 +337,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
|||||||
var isSSKBasedClosedGroup: Boolean
|
var isSSKBasedClosedGroup: Boolean
|
||||||
var groupPublicKey: String?
|
var groupPublicKey: String?
|
||||||
try {
|
try {
|
||||||
groupPublicKey = ClosedGroupsProtocol.doubleDecodeGroupID(recipient.address.toString()).toHexString()
|
groupPublicKey = GroupUtil.doubleDecodeGroupID(recipient.address.toString()).toHexString()
|
||||||
isSSKBasedClosedGroup = DatabaseFactory.getSSKDatabase(context).isSSKBasedClosedGroup(groupPublicKey)
|
isSSKBasedClosedGroup = DatabaseFactory.getSSKDatabase(context).isSSKBasedClosedGroup(groupPublicKey)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
groupPublicKey = null
|
groupPublicKey = null
|
||||||
@ -347,7 +345,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
|||||||
}
|
}
|
||||||
if (isSSKBasedClosedGroup) {
|
if (isSSKBasedClosedGroup) {
|
||||||
ClosedGroupsProtocolV2.explicitLeave(context, groupPublicKey!!)
|
ClosedGroupsProtocolV2.explicitLeave(context, groupPublicKey!!)
|
||||||
} else if (!ClosedGroupsProtocol.leaveLegacyGroup(context, recipient)) {
|
} else {
|
||||||
Toast.makeText(context, R.string.activity_home_leaving_group_failed_message, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, R.string.activity_home_leaving_group_failed_message, Toast.LENGTH_LONG).show()
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
@ -1,180 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki.protocol
|
|
||||||
|
|
||||||
import com.google.protobuf.ByteString
|
|
||||||
import org.session.libsession.messaging.jobs.Data
|
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
|
||||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
|
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job
|
|
||||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
|
||||||
import org.thoughtcrime.securesms.jobs.BaseJob
|
|
||||||
import org.session.libsignal.utilities.logging.Log
|
|
||||||
import org.thoughtcrime.securesms.loki.utilities.recipient
|
|
||||||
import org.session.libsignal.utilities.Hex
|
|
||||||
import org.session.libsignal.service.api.push.SignalServiceAddress
|
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
|
||||||
import org.session.libsignal.service.loki.protocol.closedgroups.ClosedGroupSenderKey
|
|
||||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities
|
|
||||||
import org.session.libsignal.service.loki.utilities.toHexString
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
class ClosedGroupUpdateMessageSendJob private constructor(parameters: Parameters, private val destination: String, private val kind: Kind) : BaseJob(parameters) {
|
|
||||||
|
|
||||||
sealed class Kind {
|
|
||||||
data class New(val groupPublicKey: ByteArray, val name: String, val groupPrivateKey: ByteArray, val senderKeys: Collection<ClosedGroupSenderKey>, val members: Collection<ByteArray>, val admins: Collection<ByteArray>) : Kind()
|
|
||||||
data class Info(val groupPublicKey: ByteArray, val name: String, val senderKeys: Collection<ClosedGroupSenderKey>, val members: Collection<ByteArray>, val admins: Collection<ByteArray>) : Kind()
|
|
||||||
data class SenderKeyRequest(val groupPublicKey: ByteArray) : Kind()
|
|
||||||
data class SenderKey(val groupPublicKey: ByteArray, val senderKey: ClosedGroupSenderKey) : Kind()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val KEY = "ClosedGroupUpdateMessageSendJob"
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(destination: String, kind: Kind) : this(Parameters.Builder()
|
|
||||||
.addConstraint(NetworkConstraint.KEY)
|
|
||||||
.setQueue(KEY)
|
|
||||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
|
||||||
.setMaxAttempts(1)
|
|
||||||
.build(),
|
|
||||||
destination,
|
|
||||||
kind)
|
|
||||||
|
|
||||||
override fun getFactoryKey(): String { return KEY }
|
|
||||||
|
|
||||||
override fun serialize(): Data {
|
|
||||||
val builder = Data.Builder()
|
|
||||||
builder.putString("destination", destination)
|
|
||||||
when (kind) {
|
|
||||||
is Kind.New -> {
|
|
||||||
builder.putString("kind", "New")
|
|
||||||
builder.putByteArray("groupPublicKey", kind.groupPublicKey)
|
|
||||||
builder.putString("name", kind.name)
|
|
||||||
builder.putByteArray("groupPrivateKey", kind.groupPrivateKey)
|
|
||||||
val senderKeys = kind.senderKeys.joinToString(" - ") { it.toJSON() }
|
|
||||||
builder.putString("senderKeys", senderKeys)
|
|
||||||
val members = kind.members.joinToString(" - ") { it.toHexString() }
|
|
||||||
builder.putString("members", members)
|
|
||||||
val admins = kind.admins.joinToString(" - ") { it.toHexString() }
|
|
||||||
builder.putString("admins", admins)
|
|
||||||
}
|
|
||||||
is Kind.Info -> {
|
|
||||||
builder.putString("kind", "Info")
|
|
||||||
builder.putByteArray("groupPublicKey", kind.groupPublicKey)
|
|
||||||
builder.putString("name", kind.name)
|
|
||||||
val senderKeys = kind.senderKeys.joinToString(" - ") { it.toJSON() }
|
|
||||||
builder.putString("senderKeys", senderKeys)
|
|
||||||
val members = kind.members.joinToString(" - ") { it.toHexString() }
|
|
||||||
builder.putString("members", members)
|
|
||||||
val admins = kind.admins.joinToString(" - ") { it.toHexString() }
|
|
||||||
builder.putString("admins", admins)
|
|
||||||
}
|
|
||||||
is Kind.SenderKeyRequest -> {
|
|
||||||
builder.putString("kind", "SenderKeyRequest")
|
|
||||||
builder.putByteArray("groupPublicKey", kind.groupPublicKey)
|
|
||||||
}
|
|
||||||
is Kind.SenderKey -> {
|
|
||||||
builder.putString("kind", "SenderKey")
|
|
||||||
builder.putByteArray("groupPublicKey", kind.groupPublicKey)
|
|
||||||
builder.putString("senderKey", kind.senderKey.toJSON())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onRun() {
|
|
||||||
val contentMessage = SignalServiceProtos.Content.newBuilder()
|
|
||||||
val dataMessage = SignalServiceProtos.DataMessage.newBuilder()
|
|
||||||
val closedGroupUpdate = SignalServiceProtos.ClosedGroupUpdate.newBuilder()
|
|
||||||
when (kind) {
|
|
||||||
is Kind.New -> {
|
|
||||||
closedGroupUpdate.type = SignalServiceProtos.ClosedGroupUpdate.Type.NEW
|
|
||||||
closedGroupUpdate.groupPublicKey = ByteString.copyFrom(kind.groupPublicKey)
|
|
||||||
closedGroupUpdate.name = kind.name
|
|
||||||
closedGroupUpdate.groupPrivateKey = ByteString.copyFrom(kind.groupPrivateKey)
|
|
||||||
closedGroupUpdate.addAllSenderKeys(kind.senderKeys.map { it.toProto() })
|
|
||||||
closedGroupUpdate.addAllMembers(kind.members.map { ByteString.copyFrom(it) })
|
|
||||||
closedGroupUpdate.addAllAdmins(kind.admins.map { ByteString.copyFrom(it) })
|
|
||||||
}
|
|
||||||
is Kind.Info -> {
|
|
||||||
closedGroupUpdate.type = SignalServiceProtos.ClosedGroupUpdate.Type.INFO
|
|
||||||
closedGroupUpdate.groupPublicKey = ByteString.copyFrom(kind.groupPublicKey)
|
|
||||||
closedGroupUpdate.name = kind.name
|
|
||||||
closedGroupUpdate.addAllSenderKeys(kind.senderKeys.map { it.toProto() })
|
|
||||||
closedGroupUpdate.addAllMembers(kind.members.map { ByteString.copyFrom(it) })
|
|
||||||
closedGroupUpdate.addAllAdmins(kind.admins.map { ByteString.copyFrom(it) })
|
|
||||||
}
|
|
||||||
is Kind.SenderKeyRequest -> {
|
|
||||||
closedGroupUpdate.type = SignalServiceProtos.ClosedGroupUpdate.Type.SENDER_KEY_REQUEST
|
|
||||||
closedGroupUpdate.groupPublicKey = ByteString.copyFrom(kind.groupPublicKey)
|
|
||||||
}
|
|
||||||
is Kind.SenderKey -> {
|
|
||||||
closedGroupUpdate.type = SignalServiceProtos.ClosedGroupUpdate.Type.SENDER_KEY
|
|
||||||
closedGroupUpdate.groupPublicKey = ByteString.copyFrom(kind.groupPublicKey)
|
|
||||||
closedGroupUpdate.addAllSenderKeys(listOf( kind.senderKey.toProto() ))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dataMessage.closedGroupUpdate = closedGroupUpdate.build()
|
|
||||||
contentMessage.dataMessage = dataMessage.build()
|
|
||||||
val serializedContentMessage = contentMessage.build().toByteArray()
|
|
||||||
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
|
||||||
val address = SignalServiceAddress(destination)
|
|
||||||
val recipient = recipient(context, destination)
|
|
||||||
val udAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient)
|
|
||||||
val ttl = TTLUtilities.getTTL(TTLUtilities.MessageType.ClosedGroupUpdate)
|
|
||||||
// val useFallbackEncryption = SignalProtocolStoreImpl(context).containsSession(SignalProtocolAddress(destination, 1))
|
|
||||||
val useFallbackEncryption = true
|
|
||||||
try {
|
|
||||||
// isClosedGroup can always be false as it's only used in the context of legacy closed groups
|
|
||||||
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess,
|
|
||||||
Date().time, serializedContentMessage, false, ttl, false,
|
|
||||||
useFallbackEncryption, false, false, Optional.absent())
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.d("Loki", "Failed to send closed group update message to: $destination due to error: $e.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onShouldRetry(e: Exception): Boolean {
|
|
||||||
// Disable since we have our own retrying
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCanceled() { }
|
|
||||||
|
|
||||||
class Factory : Job.Factory<ClosedGroupUpdateMessageSendJob> {
|
|
||||||
|
|
||||||
override fun create(parameters: Parameters, data: Data): ClosedGroupUpdateMessageSendJob {
|
|
||||||
val destination = data.getString("destination")
|
|
||||||
val rawKind = data.getString("kind")
|
|
||||||
val groupPublicKey = data.getByteArray("groupPublicKey")
|
|
||||||
val kind: Kind
|
|
||||||
when (rawKind) {
|
|
||||||
"New" -> {
|
|
||||||
val name = data.getString("name")
|
|
||||||
val groupPrivateKey = data.getByteArray("groupPrivateKey")
|
|
||||||
val senderKeys = data.getStringOrDefault("senderKeys", "").split(" - ").mapNotNull { ClosedGroupSenderKey.fromJSON(it) } // Can be empty
|
|
||||||
val members = data.getString("members").split(" - ").map { Hex.fromStringCondensed(it) }
|
|
||||||
val admins = data.getString("admins").split(" - ").map { Hex.fromStringCondensed(it) }
|
|
||||||
kind = Kind.New(groupPublicKey, name, groupPrivateKey, senderKeys, members, admins)
|
|
||||||
}
|
|
||||||
"Info" -> {
|
|
||||||
val name = data.getString("name")
|
|
||||||
val senderKeys = data.getStringOrDefault("senderKeys", "").split(" - ").mapNotNull { ClosedGroupSenderKey.fromJSON(it) } // Can be empty
|
|
||||||
val members = data.getString("members").split(" - ").map { Hex.fromStringCondensed(it) }
|
|
||||||
val admins = data.getString("admins").split(" - ").map { Hex.fromStringCondensed(it) }
|
|
||||||
kind = Kind.Info(groupPublicKey, name, senderKeys, members, admins)
|
|
||||||
}
|
|
||||||
"SenderKeyRequest" -> {
|
|
||||||
kind = Kind.SenderKeyRequest(groupPublicKey)
|
|
||||||
}
|
|
||||||
"SenderKey" -> {
|
|
||||||
val senderKey = ClosedGroupSenderKey.fromJSON(data.getString("senderKey"))!!
|
|
||||||
kind = Kind.SenderKey(groupPublicKey, senderKey)
|
|
||||||
}
|
|
||||||
else -> throw Exception("Invalid closed group update message kind: $rawKind.")
|
|
||||||
}
|
|
||||||
return ClosedGroupUpdateMessageSendJob(parameters, destination, kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -224,7 +224,7 @@ class ClosedGroupUpdateMessageSendJobV2 private constructor(parameters: Paramete
|
|||||||
try {
|
try {
|
||||||
// isClosedGroup can always be false as it's only used in the context of legacy closed groups
|
// isClosedGroup can always be false as it's only used in the context of legacy closed groups
|
||||||
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess,
|
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess,
|
||||||
sentTime, serializedContentMessage, false, ttl, false,
|
sentTime, serializedContentMessage, false, ttl,
|
||||||
true, false, false, Optional.absent())
|
true, false, false, Optional.absent())
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Loki", "Failed to send closed group update message to: $destination due to error: $e.")
|
Log.d("Loki", "Failed to send closed group update message to: $destination due to error: $e.")
|
||||||
|
@ -1,329 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.loki.protocol
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.annotation.WorkerThread
|
|
||||||
import com.google.protobuf.ByteString
|
|
||||||
import nl.komponents.kovenant.Promise
|
|
||||||
import nl.komponents.kovenant.deferred
|
|
||||||
import org.session.libsession.messaging.threads.Address
|
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
|
||||||
import org.session.libsession.utilities.GroupUtil
|
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos.GroupContext
|
|
||||||
import org.session.libsignal.service.loki.protocol.closedgroups.ClosedGroupRatchetCollectionType
|
|
||||||
import org.session.libsignal.service.loki.protocol.closedgroups.ClosedGroupSenderKey
|
|
||||||
import org.session.libsignal.service.loki.protocol.closedgroups.SharedSenderKeysImplementation
|
|
||||||
import org.session.libsignal.service.loki.utilities.toHexString
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
|
||||||
import org.session.libsignal.utilities.logging.Log
|
|
||||||
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager
|
|
||||||
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager.ClosedGroupOperation
|
|
||||||
import org.thoughtcrime.securesms.loki.utilities.recipient
|
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage
|
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender
|
|
||||||
import org.session.libsignal.utilities.Hex
|
|
||||||
import java.io.IOException
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
object ClosedGroupsProtocol {
|
|
||||||
|
|
||||||
sealed class Error(val description: String) : Exception() {
|
|
||||||
object NoThread : Error("Couldn't find a thread associated with the given group public key")
|
|
||||||
object NoPrivateKey : Error("Couldn't find a private key associated with the given group public key.")
|
|
||||||
object InvalidUpdate : Error("Invalid group update.")
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun leave(context: Context, groupPublicKey: String) {
|
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
|
|
||||||
val groupDB = DatabaseFactory.getGroupDatabase(context)
|
|
||||||
val groupID = doubleEncodeGroupID(groupPublicKey)
|
|
||||||
val group = groupDB.getGroup(groupID).orNull()
|
|
||||||
if (group == null) {
|
|
||||||
Log.d("Loki", "Can't leave nonexistent closed group.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val name = group.title
|
|
||||||
val oldMembers = group.members.map { it.serialize() }.toSet()
|
|
||||||
val newMembers = oldMembers.minus(userPublicKey)
|
|
||||||
return update(context, groupPublicKey, newMembers, name).get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun update(context: Context, groupPublicKey: String, members: Collection<String>, name: String): Promise<Unit, Exception> {
|
|
||||||
val deferred = deferred<Unit, Exception>()
|
|
||||||
Thread {
|
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
|
|
||||||
val sskDatabase = DatabaseFactory.getSSKDatabase(context)
|
|
||||||
val groupDB = DatabaseFactory.getGroupDatabase(context)
|
|
||||||
val groupID = doubleEncodeGroupID(groupPublicKey)
|
|
||||||
val group = groupDB.getGroup(groupID).orNull()
|
|
||||||
if (group == null) {
|
|
||||||
Log.d("Loki", "Can't update nonexistent closed group.")
|
|
||||||
return@Thread deferred.reject(Error.NoThread)
|
|
||||||
}
|
|
||||||
val oldMembers = group.members.map { it.serialize() }.toSet()
|
|
||||||
val newMembers = members.minus(oldMembers)
|
|
||||||
val membersAsData = members.map { Hex.fromStringCondensed(it) }
|
|
||||||
val admins = group.admins.map { it.serialize() }
|
|
||||||
val adminsAsData = admins.map { Hex.fromStringCondensed(it) }
|
|
||||||
val groupPrivateKey = DatabaseFactory.getSSKDatabase(context).getClosedGroupPrivateKey(groupPublicKey)
|
|
||||||
if (groupPrivateKey == null) {
|
|
||||||
Log.d("Loki", "Couldn't get private key for closed group.")
|
|
||||||
return@Thread deferred.reject(Error.NoPrivateKey)
|
|
||||||
}
|
|
||||||
val wasAnyUserRemoved = members.toSet().intersect(oldMembers) != oldMembers.toSet()
|
|
||||||
val removedMembers = oldMembers.minus(members)
|
|
||||||
val isUserLeaving = removedMembers.contains(userPublicKey)
|
|
||||||
var newSenderKeys = listOf<ClosedGroupSenderKey>()
|
|
||||||
if (wasAnyUserRemoved) {
|
|
||||||
if (isUserLeaving && removedMembers.count() != 1) {
|
|
||||||
Log.d("Loki", "Can't remove self and others simultaneously.")
|
|
||||||
return@Thread deferred.reject(Error.InvalidUpdate)
|
|
||||||
}
|
|
||||||
// Establish sessions if needed
|
|
||||||
establishSessionsWithMembersIfNeeded(context, members)
|
|
||||||
// Send the update to the existing members using established channels (don't include new ratchets as everyone should regenerate new ratchets individually)
|
|
||||||
for (member in oldMembers) {
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJob.Kind.Info(Hex.fromStringCondensed(groupPublicKey),
|
|
||||||
name, setOf(), membersAsData, adminsAsData)
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
val job = ClosedGroupUpdateMessageSendJob(member, closedGroupUpdateKind)
|
|
||||||
job.setContext(context)
|
|
||||||
job.onRun() // Run the job immediately
|
|
||||||
}
|
|
||||||
val allOldRatchets = sskDatabase.getAllClosedGroupRatchets(groupPublicKey, ClosedGroupRatchetCollectionType.Current)
|
|
||||||
for (pair in allOldRatchets) {
|
|
||||||
val senderPublicKey = pair.first
|
|
||||||
val ratchet = pair.second
|
|
||||||
val collection = ClosedGroupRatchetCollectionType.Old
|
|
||||||
sskDatabase.setClosedGroupRatchet(groupPublicKey, senderPublicKey, ratchet, collection)
|
|
||||||
}
|
|
||||||
// Delete all ratchets (it's important that this happens * after * sending out the update)
|
|
||||||
sskDatabase.removeAllClosedGroupRatchets(groupPublicKey, ClosedGroupRatchetCollectionType.Current)
|
|
||||||
// Remove the group from the user's set of public keys to poll for if the user is leaving. Otherwise generate a new ratchet and
|
|
||||||
// send it out to all members (minus the removed ones) using established channels.
|
|
||||||
if (isUserLeaving) {
|
|
||||||
sskDatabase.removeClosedGroupPrivateKey(groupPublicKey)
|
|
||||||
groupDB.setActive(groupID, false)
|
|
||||||
groupDB.removeMember(groupID, Address.fromSerialized(userPublicKey))
|
|
||||||
// Notify the PN server
|
|
||||||
LokiPushNotificationManager.performOperation(context, ClosedGroupOperation.Unsubscribe, groupPublicKey, userPublicKey)
|
|
||||||
} else {
|
|
||||||
// Send closed group update messages to any new members using established channels
|
|
||||||
for (member in newMembers) {
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJob.Kind.New(Hex.fromStringCondensed(groupPublicKey), name,
|
|
||||||
Hex.fromStringCondensed(groupPrivateKey), listOf(), membersAsData, adminsAsData)
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
val job = ClosedGroupUpdateMessageSendJob(member, closedGroupUpdateKind)
|
|
||||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
|
||||||
}
|
|
||||||
// Send out the user's new ratchet to all members (minus the removed ones) using established channels
|
|
||||||
val userRatchet = SharedSenderKeysImplementation.shared.generateRatchet(groupPublicKey, userPublicKey)
|
|
||||||
val userSenderKey = ClosedGroupSenderKey(Hex.fromStringCondensed(userRatchet.chainKey), userRatchet.keyIndex, Hex.fromStringCondensed(userPublicKey))
|
|
||||||
for (member in members) {
|
|
||||||
if (member == userPublicKey) { continue }
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJob.Kind.SenderKey(Hex.fromStringCondensed(groupPublicKey), userSenderKey)
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
val job = ClosedGroupUpdateMessageSendJob(member, closedGroupUpdateKind)
|
|
||||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (newMembers.isNotEmpty()) {
|
|
||||||
// Generate ratchets for any new members
|
|
||||||
newSenderKeys = newMembers.map { publicKey ->
|
|
||||||
val ratchet = SharedSenderKeysImplementation.shared.generateRatchet(groupPublicKey, publicKey)
|
|
||||||
ClosedGroupSenderKey(Hex.fromStringCondensed(ratchet.chainKey), ratchet.keyIndex, Hex.fromStringCondensed(publicKey))
|
|
||||||
}
|
|
||||||
// Send a closed group update message to the existing members with the new members' ratchets (this message is aimed at the group)
|
|
||||||
val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJob.Kind.Info(Hex.fromStringCondensed(groupPublicKey), name,
|
|
||||||
newSenderKeys, membersAsData, adminsAsData)
|
|
||||||
val job = ClosedGroupUpdateMessageSendJob(groupPublicKey, closedGroupUpdateKind)
|
|
||||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
|
||||||
// Establish sessions if needed
|
|
||||||
establishSessionsWithMembersIfNeeded(context, newMembers)
|
|
||||||
// Send closed group update messages to the new members using established channels
|
|
||||||
var allSenderKeys = sskDatabase.getAllClosedGroupSenderKeys(groupPublicKey, ClosedGroupRatchetCollectionType.Current)
|
|
||||||
allSenderKeys = allSenderKeys.union(newSenderKeys)
|
|
||||||
for (member in newMembers) {
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJob.Kind.New(Hex.fromStringCondensed(groupPublicKey), name,
|
|
||||||
Hex.fromStringCondensed(groupPrivateKey), allSenderKeys, membersAsData, adminsAsData)
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
val job = ClosedGroupUpdateMessageSendJob(member, closedGroupUpdateKind)
|
|
||||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val allSenderKeys = sskDatabase.getAllClosedGroupSenderKeys(groupPublicKey, ClosedGroupRatchetCollectionType.Current)
|
|
||||||
val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJob.Kind.Info(Hex.fromStringCondensed(groupPublicKey), name,
|
|
||||||
allSenderKeys, membersAsData, adminsAsData)
|
|
||||||
val job = ClosedGroupUpdateMessageSendJob(groupPublicKey, closedGroupUpdateKind)
|
|
||||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
|
||||||
}
|
|
||||||
// Update the group
|
|
||||||
groupDB.updateTitle(groupID, name)
|
|
||||||
if (!isUserLeaving) {
|
|
||||||
// The call below sets isActive to true, so if the user is leaving we have to use groupDB.remove(...) instead
|
|
||||||
groupDB.updateMembers(groupID, members.map { Address.fromSerialized(it) })
|
|
||||||
}
|
|
||||||
// Notify the user
|
|
||||||
val infoType = if (isUserLeaving) GroupContext.Type.QUIT else GroupContext.Type.UPDATE
|
|
||||||
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false))
|
|
||||||
insertOutgoingInfoMessage(context, groupID, infoType, name, members, admins, threadID)
|
|
||||||
deferred.resolve(Unit)
|
|
||||||
}.start()
|
|
||||||
return deferred.promise
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun requestSenderKey(context: Context, groupPublicKey: String, senderPublicKey: String) {
|
|
||||||
Log.d("Loki", "Requesting sender key for group public key: $groupPublicKey, sender public key: $senderPublicKey.")
|
|
||||||
// Establish session if needed
|
|
||||||
ApplicationContext.getInstance(context).sendSessionRequestIfNeeded(senderPublicKey)
|
|
||||||
// Send the request
|
|
||||||
val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJob.Kind.SenderKeyRequest(Hex.fromStringCondensed(groupPublicKey))
|
|
||||||
val job = ClosedGroupUpdateMessageSendJob(senderPublicKey, closedGroupUpdateKind)
|
|
||||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun shouldIgnoreContentMessage(context: Context, address: Address, groupID: String?, senderPublicKey: String): Boolean {
|
|
||||||
if (!address.isClosedGroup || groupID == null) { return false }
|
|
||||||
/*
|
|
||||||
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)
|
|
||||||
return !members.contains(recipient(context, senderPublicKey))
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun getMessageDestinations(context: Context, groupID: String): List<Address> {
|
|
||||||
if (GroupUtil.isOpenGroup(groupID)) {
|
|
||||||
return listOf(Address.fromSerialized(groupID))
|
|
||||||
} else {
|
|
||||||
var groupPublicKey: String? = null
|
|
||||||
try {
|
|
||||||
groupPublicKey = doubleDecodeGroupID(groupID).toHexString()
|
|
||||||
} catch (exception: Exception) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
if (groupPublicKey != null && DatabaseFactory.getSSKDatabase(context).isSSKBasedClosedGroup(groupPublicKey)) {
|
|
||||||
return listOf(Address.fromSerialized(groupPublicKey))
|
|
||||||
} else {
|
|
||||||
return DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupID, false).map { it.address }
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
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()
|
|
||||||
val userMasterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
|
|
||||||
if (userMasterPublicKey != null && result.contains(Address.fromSerialized(userMasterPublicKey))) {
|
|
||||||
result.remove(Address.fromSerialized(userMasterPublicKey))
|
|
||||||
}
|
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
|
||||||
if (userPublicKey != null && result.contains(Address.fromSerialized(userPublicKey))) {
|
|
||||||
result.remove(Address.fromSerialized(userPublicKey))
|
|
||||||
}
|
|
||||||
result.toList()
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun leaveLegacyGroup(context: Context, recipient: Recipient): Boolean {
|
|
||||||
if (!recipient.address.isClosedGroup) { return true }
|
|
||||||
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
|
||||||
val message = createGroupLeaveMessage(context, recipient)
|
|
||||||
if (threadID < 0 || message == null) { return false }
|
|
||||||
MessageSender.send(context, message, threadID, false, null)
|
|
||||||
/*
|
|
||||||
val masterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
|
|
||||||
val publicKeyToRemove = masterPublicKey ?: TextSecurePreferences.getLocalNumber(context)
|
|
||||||
*/
|
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
|
|
||||||
val groupDatabase = DatabaseFactory.getGroupDatabase(context)
|
|
||||||
val groupID = recipient.address.toGroupString()
|
|
||||||
groupDatabase.setActive(groupID, false)
|
|
||||||
groupDatabase.removeMember(groupID, Address.fromSerialized(userPublicKey))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun establishSessionsWithMembersIfNeeded(context: Context, members: Collection<String>) {
|
|
||||||
@Suppress("NAME_SHADOWING") val members = members.toMutableSet()
|
|
||||||
/*
|
|
||||||
val allDevices = members.flatMap { member ->
|
|
||||||
MultiDeviceProtocol.shared.getAllLinkedDevices(member)
|
|
||||||
}.toMutableSet()
|
|
||||||
val userMasterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
|
|
||||||
if (userMasterPublicKey != null && allDevices.contains(userMasterPublicKey)) {
|
|
||||||
allDevices.remove(userMasterPublicKey)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)
|
|
||||||
if (userPublicKey != null && members.contains(userPublicKey)) {
|
|
||||||
members.remove(userPublicKey)
|
|
||||||
}
|
|
||||||
for (member in members) {
|
|
||||||
ApplicationContext.getInstance(context).sendSessionRequestIfNeeded(member)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun insertOutgoingInfoMessage(context: Context, groupID: String, type: GroupContext.Type, name: String,
|
|
||||||
members: Collection<String>, admins: Collection<String>, threadID: Long) {
|
|
||||||
val recipient = Recipient.from(context, Address.fromSerialized(groupID), false)
|
|
||||||
val groupContextBuilder = GroupContext.newBuilder()
|
|
||||||
.setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID)))
|
|
||||||
.setType(type)
|
|
||||||
.setName(name)
|
|
||||||
.addAllMembers(members)
|
|
||||||
.addAllAdmins(admins)
|
|
||||||
val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, 0, null, listOf(), listOf())
|
|
||||||
val mmsDB = DatabaseFactory.getMmsDatabase(context)
|
|
||||||
val infoMessageID = mmsDB.insertMessageOutbox(infoMessage, threadID, false, null)
|
|
||||||
mmsDB.markAsSent(infoMessageID, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Signal group ID handling is weird. The ID is double encoded in the database, but not in a `GroupContext`.
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(IOException::class)
|
|
||||||
fun doubleEncodeGroupID(groupPublicKey: String): String {
|
|
||||||
return GroupUtil.getEncodedClosedGroupID(GroupUtil.getEncodedClosedGroupID(Hex.fromStringCondensed(groupPublicKey)).toByteArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(IOException::class)
|
|
||||||
fun doubleDecodeGroupID(groupID: String): ByteArray {
|
|
||||||
return GroupUtil.getDecodedGroupIDAsData(GroupUtil.getDecodedGroupID(groupID))
|
|
||||||
}
|
|
||||||
|
|
||||||
@WorkerThread
|
|
||||||
fun createGroupLeaveMessage(context: Context, groupRecipient: Recipient): OutgoingGroupMediaMessage? {
|
|
||||||
val encodedGroupId = groupRecipient.address.toGroupString()
|
|
||||||
val groupDatabase = DatabaseFactory.getGroupDatabase(context)
|
|
||||||
if (!groupDatabase.isActive(encodedGroupId)) {
|
|
||||||
Log.w("Loki", "Group has already been left.")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
val decodedGroupId: ByteString
|
|
||||||
try {
|
|
||||||
decodedGroupId = ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(encodedGroupId))
|
|
||||||
} catch (e: IOException) {
|
|
||||||
Log.w("Loki", "Failed to decode group ID.", e)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
val groupContext = GroupContext.newBuilder()
|
|
||||||
.setId(decodedGroupId)
|
|
||||||
.setType(GroupContext.Type.QUIT)
|
|
||||||
.build()
|
|
||||||
return OutgoingGroupMediaMessage(groupRecipient, groupContext, null, 0, null, emptyList(), emptyList())
|
|
||||||
}
|
|
||||||
}
|
|
@ -56,7 +56,7 @@ class NullMessageSendJob private constructor(parameters: Parameters, private val
|
|||||||
val ttl = TTLUtilities.getTTL(TTLUtilities.MessageType.Ephemeral)
|
val ttl = TTLUtilities.getTTL(TTLUtilities.MessageType.Ephemeral)
|
||||||
try {
|
try {
|
||||||
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess,
|
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess,
|
||||||
Date().time, serializedContentMessage, false, ttl, false,
|
Date().time, serializedContentMessage, false, ttl,
|
||||||
false, false, false, Optional.absent())
|
false, false, false, Optional.absent())
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Loki", "Failed to send null message to: $publicKey due to error: $e.")
|
Log.d("Loki", "Failed to send null message to: $publicKey due to error: $e.")
|
||||||
|
@ -96,9 +96,6 @@ object SessionManagementProtocol {
|
|||||||
fun triggerSessionRestorationUI(context: Context, publicKey: String, errorTimestamp: Long) {
|
fun triggerSessionRestorationUI(context: Context, publicKey: String, errorTimestamp: Long) {
|
||||||
val recipient = recipient(context, publicKey)
|
val recipient = recipient(context, publicKey)
|
||||||
if (recipient.isGroupRecipient) { return }
|
if (recipient.isGroupRecipient) { return }
|
||||||
if (TextSecurePreferences.getRestorationTime(context) > errorTimestamp) {
|
|
||||||
return ApplicationContext.getInstance(context).sendSessionRequestIfNeeded(publicKey)
|
|
||||||
}
|
|
||||||
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
||||||
DatabaseFactory.getLokiThreadDatabase(context).addSessionRestoreDevice(threadID, publicKey)
|
DatabaseFactory.getLokiThreadDatabase(context).addSessionRestoreDevice(threadID, publicKey)
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
|
|||||||
cameraButton = findViewById(R.id.mediasend_camera_button);
|
cameraButton = findViewById(R.id.mediasend_camera_button);
|
||||||
|
|
||||||
viewModel = new ViewModelProvider(this, new MediaSendViewModel.Factory(getApplication(), new MediaRepository())).get(MediaSendViewModel.class);
|
viewModel = new ViewModelProvider(this, new MediaSendViewModel.Factory(getApplication(), new MediaRepository())).get(MediaSendViewModel.class);
|
||||||
recipient = Recipient.from(this, Address.Companion.fromSerialized(getIntent().getStringExtra(KEY_ADDRESS)), true);
|
recipient = Recipient.from(this, Address.fromSerialized(getIntent().getStringExtra(KEY_ADDRESS)), true);
|
||||||
|
|
||||||
viewModel.onBodyChanged(getIntent().getStringExtra(KEY_BODY));
|
viewModel.onBodyChanged(getIntent().getStringExtra(KEY_BODY));
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ public class IncomingMediaMessage {
|
|||||||
this.quote = quote.orNull();
|
this.quote = quote.orNull();
|
||||||
this.unidentified = unidentified;
|
this.unidentified = unidentified;
|
||||||
|
|
||||||
if (group.isPresent()) this.groupId = Address.Companion.fromSerialized(GroupUtil.INSTANCE.getEncodedId(group.get()));
|
if (group.isPresent()) this.groupId = Address.fromSerialized(GroupUtil.INSTANCE.getEncodedId(group.get()));
|
||||||
else this.groupId = null;
|
else this.groupId = null;
|
||||||
|
|
||||||
this.attachments.addAll(PointerAttachment.forPointers(attachments));
|
this.attachments.addAll(PointerAttachment.forPointers(attachments));
|
||||||
|
@ -50,7 +50,7 @@ public class QuoteId {
|
|||||||
public static @Nullable QuoteId deserialize(@NonNull String serialized) {
|
public static @Nullable QuoteId deserialize(@NonNull String serialized) {
|
||||||
try {
|
try {
|
||||||
JSONObject json = new JSONObject(serialized);
|
JSONObject json = new JSONObject(serialized);
|
||||||
return new QuoteId(json.getLong(ID), Address.Companion.fromSerialized(json.getString(AUTHOR)));
|
return new QuoteId(json.getLong(ID), Address.fromSerialized(json.getString(AUTHOR)));
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
Log.e(TAG, "Failed to deserialize from json", e);
|
Log.e(TAG, "Failed to deserialize from json", e);
|
||||||
return null;
|
return null;
|
||||||
|
@ -128,7 +128,7 @@ public class SearchRepository {
|
|||||||
|
|
||||||
private CursorList<ThreadRecord> queryConversations(@NonNull String query) {
|
private CursorList<ThreadRecord> queryConversations(@NonNull String query) {
|
||||||
List<String> numbers = contactAccessor.getNumbersForThreadSearchFilter(context, query);
|
List<String> numbers = contactAccessor.getNumbersForThreadSearchFilter(context, query);
|
||||||
List<Address> addresses = Stream.of(numbers).map(number -> Address.Companion.fromExternal(context, number)).toList();
|
List<Address> addresses = Stream.of(numbers).map(number -> Address.fromExternal(context, number)).toList();
|
||||||
|
|
||||||
Cursor conversations = threadDatabase.getFilteredConversationList(addresses);
|
Cursor conversations = threadDatabase.getFilteredConversationList(addresses);
|
||||||
return conversations != null ? new CursorList<>(conversations, new ThreadModelBuilder(threadDatabase))
|
return conversations != null ? new CursorList<>(conversations, new ThreadModelBuilder(threadDatabase))
|
||||||
@ -179,7 +179,7 @@ public class SearchRepository {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Recipient build(@NonNull Cursor cursor) {
|
public Recipient build(@NonNull Cursor cursor) {
|
||||||
Address address = Address.Companion.fromExternal(context, cursor.getString(1));
|
Address address = Address.fromExternal(context, cursor.getString(1));
|
||||||
return Recipient.from(context, address, false);
|
return Recipient.from(context, address, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,8 +208,8 @@ public class SearchRepository {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MessageResult build(@NonNull Cursor cursor) {
|
public MessageResult build(@NonNull Cursor cursor) {
|
||||||
Address conversationAddress = Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndex(SearchDatabase.CONVERSATION_ADDRESS)));
|
Address conversationAddress = Address.fromSerialized(cursor.getString(cursor.getColumnIndex(SearchDatabase.CONVERSATION_ADDRESS)));
|
||||||
Address messageAddress = Address.Companion.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(SearchDatabase.MESSAGE_ADDRESS)));
|
Address messageAddress = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(SearchDatabase.MESSAGE_ADDRESS)));
|
||||||
Recipient conversationRecipient = Recipient.from(context, conversationAddress, false);
|
Recipient conversationRecipient = Recipient.from(context, conversationAddress, false);
|
||||||
Recipient messageRecipient = Recipient.from(context, messageAddress, false);
|
Recipient messageRecipient = Recipient.from(context, messageAddress, false);
|
||||||
String body = cursor.getString(cursor.getColumnIndexOrThrow(SearchDatabase.SNIPPET));
|
String body = cursor.getString(cursor.getColumnIndexOrThrow(SearchDatabase.SNIPPET));
|
||||||
|
@ -68,7 +68,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
|
|||||||
public void setExpirationTimer(@Nullable Long messageID, int duration, @NotNull String senderPublicKey, @NotNull SignalServiceProtos.Content content) {
|
public void setExpirationTimer(@Nullable Long messageID, int duration, @NotNull String senderPublicKey, @NotNull SignalServiceProtos.Content content) {
|
||||||
try {
|
try {
|
||||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||||
Address address = Address.Companion.fromSerialized(senderPublicKey);
|
Address address = Address.fromSerialized(senderPublicKey);
|
||||||
Recipient recipient = Recipient.from(context, address, false);
|
Recipient recipient = Recipient.from(context, address, false);
|
||||||
Optional<SignalServiceGroup> groupInfo = Optional.absent();
|
Optional<SignalServiceGroup> groupInfo = Optional.absent();
|
||||||
if (content.getDataMessage().hasGroup()) {
|
if (content.getDataMessage().hasGroup()) {
|
||||||
|
@ -47,7 +47,7 @@ public class QuickResponseService extends IntentService {
|
|||||||
number = URLDecoder.decode(number);
|
number = URLDecoder.decode(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
Address address = Address.Companion.fromExternal(this, number);
|
Address address = Address.fromExternal(this, number);
|
||||||
Recipient recipient = Recipient.from(this, address, false);
|
Recipient recipient = Recipient.from(this, address, false);
|
||||||
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
|
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
|
||||||
long expiresIn = recipient.getExpireMessages() * 1000L;
|
long expiresIn = recipient.getExpireMessages() * 1000L;
|
||||||
|
@ -47,7 +47,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
|
|
||||||
public IncomingTextMessage(@NonNull Context context, @NonNull SmsMessage message, int subscriptionId) {
|
public IncomingTextMessage(@NonNull Context context, @NonNull SmsMessage message, int subscriptionId) {
|
||||||
this.message = message.getDisplayMessageBody();
|
this.message = message.getDisplayMessageBody();
|
||||||
this.sender = Address.Companion.fromSerialized(message.getDisplayOriginatingAddress());
|
this.sender = Address.fromSerialized(message.getDisplayOriginatingAddress());
|
||||||
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||||
this.protocol = message.getProtocolIdentifier();
|
this.protocol = message.getProtocolIdentifier();
|
||||||
this.serviceCenterAddress = message.getServiceCenterAddress();
|
this.serviceCenterAddress = message.getServiceCenterAddress();
|
||||||
@ -79,7 +79,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
this.unidentified = unidentified;
|
this.unidentified = unidentified;
|
||||||
|
|
||||||
if (group.isPresent()) {
|
if (group.isPresent()) {
|
||||||
this.groupId = Address.Companion.fromSerialized(GroupUtil.getEncodedId(group.get()));
|
this.groupId = Address.fromSerialized(GroupUtil.getEncodedId(group.get()));
|
||||||
} else {
|
} else {
|
||||||
this.groupId = null;
|
this.groupId = null;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ public class MessageSender {
|
|||||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||||
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
||||||
OutgoingMediaMessage message = mmsDatabase.getOutgoingMessage(messageId);
|
OutgoingMediaMessage message = mmsDatabase.getOutgoingMessage(messageId);
|
||||||
SyncMessageId syncId = new SyncMessageId(Address.Companion.fromSerialized(TextSecurePreferences.getLocalNumber(context)), message.getSentTimeMillis());
|
SyncMessageId syncId = new SyncMessageId(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)), message.getSentTimeMillis());
|
||||||
|
|
||||||
for (Attachment attachment : message.getAttachments()) {
|
for (Attachment attachment : message.getAttachments()) {
|
||||||
attachmentDatabase.markAttachmentUploaded(messageId, attachment);
|
attachmentDatabase.markAttachmentUploaded(messageId, attachment);
|
||||||
@ -249,7 +249,7 @@ public class MessageSender {
|
|||||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||||
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
||||||
SmsMessageRecord message = smsDatabase.getMessage(messageId);
|
SmsMessageRecord message = smsDatabase.getMessage(messageId);
|
||||||
SyncMessageId syncId = new SyncMessageId(Address.Companion.fromSerialized(TextSecurePreferences.getLocalNumber(context)), message.getDateSent());
|
SyncMessageId syncId = new SyncMessageId(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)), message.getDateSent());
|
||||||
|
|
||||||
smsDatabase.markAsSent(messageId, true);
|
smsDatabase.markAsSent(messageId, true);
|
||||||
smsDatabase.markUnidentified(messageId, true);
|
smsDatabase.markUnidentified(messageId, true);
|
||||||
|
@ -152,15 +152,18 @@ class Address private constructor(address: String) : Parcelable, Comparable<Addr
|
|||||||
val UNKNOWN = Address("Unknown")
|
val UNKNOWN = Address("Unknown")
|
||||||
private val TAG = Address::class.java.simpleName
|
private val TAG = Address::class.java.simpleName
|
||||||
private val cachedFormatter = AtomicReference<Pair<String, ExternalAddressFormatter>>()
|
private val cachedFormatter = AtomicReference<Pair<String, ExternalAddressFormatter>>()
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun fromSerialized(serialized: String): Address {
|
fun fromSerialized(serialized: String): Address {
|
||||||
return Address(serialized)
|
return Address(serialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
fun fromExternal(context: Context, external: String?): Address {
|
fun fromExternal(context: Context, external: String?): Address {
|
||||||
return fromSerialized(external!!)
|
return fromSerialized(external!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
fun fromSerializedList(serialized: String, delimiter: Char): List<Address> {
|
fun fromSerializedList(serialized: String, delimiter: Char): List<Address> {
|
||||||
val escapedAddresses = DelimiterUtil.split(serialized, delimiter)
|
val escapedAddresses = DelimiterUtil.split(serialized, delimiter)
|
||||||
val addresses: MutableList<Address> = LinkedList()
|
val addresses: MutableList<Address> = LinkedList()
|
||||||
@ -170,6 +173,7 @@ class Address private constructor(address: String) : Parcelable, Comparable<Addr
|
|||||||
return addresses
|
return addresses
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
fun toSerializedList(addresses: List<Address>, delimiter: Char): String {
|
fun toSerializedList(addresses: List<Address>, delimiter: Char): String {
|
||||||
Collections.sort(addresses)
|
Collections.sort(addresses)
|
||||||
val escapedAddresses: MutableList<String> = LinkedList()
|
val escapedAddresses: MutableList<String> = LinkedList()
|
||||||
|
@ -216,7 +216,7 @@ public class SignalServiceMessageSender {
|
|||||||
SignalServiceReceiptMessage message)
|
SignalServiceReceiptMessage message)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
byte[] content = createReceiptContent(message);
|
byte[] content = createReceiptContent(message);
|
||||||
boolean useFallbackEncryption = SessionManagementProtocol.shared.shouldMessageUseFallbackEncryption(message, recipient.getNumber(), store);
|
boolean useFallbackEncryption = true;
|
||||||
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), message.getWhen(), content, false, message.getTTL(), useFallbackEncryption);
|
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), message.getWhen(), content, false, message.getTTL(), useFallbackEncryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,9 +244,8 @@ public class SignalServiceMessageSender {
|
|||||||
{
|
{
|
||||||
byte[] content = createMessageContent(message, recipient);
|
byte[] content = createMessageContent(message, recipient);
|
||||||
long timestamp = message.getTimestamp();
|
long timestamp = message.getTimestamp();
|
||||||
boolean useFallbackEncryption = SessionManagementProtocol.shared.shouldMessageUseFallbackEncryption(message, recipient.getNumber(), store);
|
|
||||||
boolean isClosedGroup = message.group.isPresent() && message.group.get().getGroupType() == SignalServiceGroup.GroupType.SIGNAL;
|
boolean isClosedGroup = message.group.isPresent() && message.group.get().getGroupType() == SignalServiceGroup.GroupType.SIGNAL;
|
||||||
SendMessageResult result = sendMessage(messageID, recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false, message.getTTL(), useFallbackEncryption, isClosedGroup, message.hasVisibleContent(), message.getSyncTarget());
|
SendMessageResult result = sendMessage(messageID, recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false, message.getTTL(), true, isClosedGroup, message.hasVisibleContent(), message.getSyncTarget());
|
||||||
|
|
||||||
// // Loki - This shouldn't get invoked for note to self
|
// // Loki - This shouldn't get invoked for note to self
|
||||||
// boolean wouldSignalSendSyncMessage = (result.getSuccess() != null && result.getSuccess().isNeedsSync()) || unidentifiedAccess.isPresent();
|
// boolean wouldSignalSendSyncMessage = (result.getSuccess() != null && result.getSuccess().isNeedsSync()) || unidentifiedAccess.isPresent();
|
||||||
@ -854,8 +853,7 @@ public class SignalServiceMessageSender {
|
|||||||
SignalServiceAddress recipient = recipientIterator.next();
|
SignalServiceAddress recipient = recipientIterator.next();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
boolean useFallbackEncryption = SessionManagementProtocol.shared.shouldMessageUseFallbackEncryption(content, recipient.getNumber(), store);
|
SendMessageResult result = sendMessage(messageID, recipient, unidentifiedAccessIterator.next(), timestamp, content, online, ttl, true, isClosedGroup, notifyPNServer, Optional.absent());
|
||||||
SendMessageResult result = sendMessage(messageID, recipient, unidentifiedAccessIterator.next(), timestamp, content, online, ttl, useFallbackEncryption, isClosedGroup, notifyPNServer, Optional.absent());
|
|
||||||
results.add(result);
|
results.add(result);
|
||||||
} catch (UnregisteredUserException e) {
|
} catch (UnregisteredUserException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
|
@ -25,14 +25,6 @@ public class SessionManagementProtocol(private val sessionResetImpl: SessionRese
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Sending
|
// region Sending
|
||||||
public fun shouldMessageUseFallbackEncryption(message: Any, publicKey: String, store: SignalProtocolStore): Boolean {
|
|
||||||
// if (sskDatabase.isSSKBasedClosedGroup(publicKey)) { return true } // We don't actually use fallback encryption but this indicates that we don't need a session
|
|
||||||
// if (message is SignalServiceDataMessage && message.preKeyBundle.isPresent) { return true; } // This covers session requests as well as end session messages
|
|
||||||
// val recipient = SignalProtocolAddress(publicKey, SignalServiceAddress.DEFAULT_DEVICE_ID)
|
|
||||||
// return !store.containsSession(recipient)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called after an end session message is sent.
|
* Called after an end session message is sent.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user