mirror of
https://github.com/AsamK/signal-cli
synced 2025-09-02 20:40:38 +00:00
Merge remote-tracking branch 'refs/remotes/origin/master'
This commit is contained in:
commit
54583161e2
12 changed files with 228 additions and 172 deletions
|
@ -58,7 +58,6 @@ import org.asamk.signal.manager.storage.stickers.StickerPackId;
|
|||
import org.asamk.signal.manager.util.KeyUtils;
|
||||
import org.asamk.signal.manager.util.StickerUtils;
|
||||
import org.asamk.signal.manager.util.Utils;
|
||||
import org.signal.libsignal.metadata.ProtocolUntrustedIdentityException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
|
@ -165,8 +164,7 @@ public class Manager implements Closeable {
|
|||
return LEGACY_LOCK::unlock;
|
||||
}
|
||||
};
|
||||
this.dependencies = new SignalDependencies(account.getSelfAddress(),
|
||||
serviceEnvironmentConfig,
|
||||
this.dependencies = new SignalDependencies(serviceEnvironmentConfig,
|
||||
userAgent,
|
||||
credentialsProvider,
|
||||
account.getSignalProtocolStore(),
|
||||
|
@ -187,8 +185,6 @@ public class Manager implements Closeable {
|
|||
avatarStore,
|
||||
account.getProfileStore()::getProfileKey,
|
||||
unidentifiedAccessHelper::getAccessFor,
|
||||
dependencies::getProfileService,
|
||||
dependencies::getMessageReceiver,
|
||||
this::resolveSignalServiceAddress);
|
||||
final GroupV2Helper groupV2Helper = new GroupV2Helper(profileHelper::getRecipientProfileKeyCredential,
|
||||
this::getRecipientProfile,
|
||||
|
@ -221,8 +217,7 @@ public class Manager implements Closeable {
|
|||
this::resolveSignalServiceAddress);
|
||||
|
||||
this.context = new Context(account,
|
||||
dependencies.getAccountManager(),
|
||||
dependencies.getMessageReceiver(),
|
||||
dependencies,
|
||||
stickerPackStore,
|
||||
sendHelper,
|
||||
groupHelper,
|
||||
|
@ -386,6 +381,13 @@ public class Manager implements Closeable {
|
|||
}
|
||||
|
||||
public void deleteAccount() throws IOException {
|
||||
try {
|
||||
pinHelper.removeRegistrationLockPin();
|
||||
} catch (UnauthenticatedResponseException e) {
|
||||
logger.warn("Failed to remove registration lock pin");
|
||||
}
|
||||
account.setRegistrationLockPin(null, null);
|
||||
|
||||
dependencies.getAccountManager().deleteAccount();
|
||||
|
||||
account.setRegistered(false);
|
||||
|
@ -818,37 +820,33 @@ public class Manager implements Closeable {
|
|||
) {
|
||||
var envelope = cachedMessage.loadEnvelope();
|
||||
if (envelope == null) {
|
||||
cachedMessage.delete();
|
||||
return null;
|
||||
}
|
||||
SignalServiceContent content = null;
|
||||
List<HandleAction> actions = null;
|
||||
if (!envelope.isReceipt()) {
|
||||
try {
|
||||
content = dependencies.getCipher().decrypt(envelope);
|
||||
} catch (ProtocolUntrustedIdentityException e) {
|
||||
if (System.currentTimeMillis() - envelope.getServerDeliveredTimestamp() > 1000L * 60 * 60 * 24 * 30) {
|
||||
// Envelope is more than a month old, cleaning up.
|
||||
cachedMessage.delete();
|
||||
return null;
|
||||
}
|
||||
if (!envelope.hasSourceUuid()) {
|
||||
final var identifier = e.getSender();
|
||||
final var recipientId = account.getRecipientStore().resolveRecipient(identifier);
|
||||
try {
|
||||
account.getMessageCache().replaceSender(cachedMessage, recipientId);
|
||||
} catch (IOException ioException) {
|
||||
logger.warn("Failed to move cached message to recipient folder: {}", ioException.getMessage());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (Exception er) {
|
||||
// All other errors are not recoverable, so delete the cached message
|
||||
|
||||
final var result = incomingMessageHandler.handleRetryEnvelope(envelope, ignoreAttachments, handler);
|
||||
final var actions = result.first();
|
||||
final var exception = result.second();
|
||||
|
||||
if (exception instanceof UntrustedIdentityException) {
|
||||
if (System.currentTimeMillis() - envelope.getServerDeliveredTimestamp() > 1000L * 60 * 60 * 24 * 30) {
|
||||
// Envelope is more than a month old, cleaning up.
|
||||
cachedMessage.delete();
|
||||
return null;
|
||||
}
|
||||
actions = incomingMessageHandler.handleMessage(envelope, content, ignoreAttachments);
|
||||
if (!envelope.hasSourceUuid()) {
|
||||
final var identifier = ((UntrustedIdentityException) exception).getSender();
|
||||
final var recipientId = account.getRecipientStore().resolveRecipient(identifier);
|
||||
try {
|
||||
account.getMessageCache().replaceSender(cachedMessage, recipientId);
|
||||
} catch (IOException ioException) {
|
||||
logger.warn("Failed to move cached message to recipient folder: {}", ioException.getMessage());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
handler.handleMessage(envelope, content, null);
|
||||
|
||||
// If successful and for all other errors that are not recoverable, delete the cached message
|
||||
cachedMessage.delete();
|
||||
return actions;
|
||||
}
|
||||
|
@ -1147,10 +1145,6 @@ public class Manager implements Closeable {
|
|||
}
|
||||
|
||||
public SignalServiceAddress resolveSignalServiceAddress(SignalServiceAddress address) {
|
||||
if (address.matches(account.getSelfAddress())) {
|
||||
return account.getSelfAddress();
|
||||
}
|
||||
|
||||
return resolveSignalServiceAddress(resolveRecipient(address));
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.asamk.signal.manager;
|
|||
import org.asamk.signal.manager.config.ServiceConfig;
|
||||
import org.asamk.signal.manager.config.ServiceEnvironmentConfig;
|
||||
import org.signal.libsignal.metadata.certificate.CertificateValidator;
|
||||
import org.signal.zkgroup.profiles.ClientZkProfileOperations;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.KeyBackupService;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
|
@ -18,32 +17,41 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
|
|||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.services.ProfileService;
|
||||
import org.whispersystems.signalservice.api.util.SleepTimer;
|
||||
import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
|
||||
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
|
||||
import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.asamk.signal.manager.config.ServiceConfig.capabilities;
|
||||
|
||||
public class SignalDependencies {
|
||||
|
||||
private final SignalServiceAccountManager accountManager;
|
||||
private final GroupsV2Api groupsV2Api;
|
||||
private final GroupsV2Operations groupsV2Operations;
|
||||
private final Object LOCK = new Object();
|
||||
|
||||
private final SignalWebSocket signalWebSocket;
|
||||
private final SignalServiceMessageReceiver messageReceiver;
|
||||
private final SignalServiceMessageSender messageSender;
|
||||
private final ServiceEnvironmentConfig serviceEnvironmentConfig;
|
||||
private final String userAgent;
|
||||
private final DynamicCredentialsProvider credentialsProvider;
|
||||
private final SignalServiceDataStore dataStore;
|
||||
private final ExecutorService executor;
|
||||
private final SignalSessionLock sessionLock;
|
||||
|
||||
private final KeyBackupService keyBackupService;
|
||||
private final ProfileService profileService;
|
||||
private final SignalServiceCipher cipher;
|
||||
private SignalServiceAccountManager accountManager;
|
||||
private GroupsV2Api groupsV2Api;
|
||||
private GroupsV2Operations groupsV2Operations;
|
||||
private ClientZkOperations clientZkOperations;
|
||||
|
||||
private SignalWebSocket signalWebSocket;
|
||||
private SignalServiceMessageReceiver messageReceiver;
|
||||
private SignalServiceMessageSender messageSender;
|
||||
|
||||
private KeyBackupService keyBackupService;
|
||||
private ProfileService profileService;
|
||||
private SignalServiceCipher cipher;
|
||||
|
||||
public SignalDependencies(
|
||||
final SignalServiceAddress selfAddress,
|
||||
final ServiceEnvironmentConfig serviceEnvironmentConfig,
|
||||
final String userAgent,
|
||||
final DynamicCredentialsProvider credentialsProvider,
|
||||
|
@ -51,100 +59,134 @@ public class SignalDependencies {
|
|||
final ExecutorService executor,
|
||||
final SignalSessionLock sessionLock
|
||||
) {
|
||||
this.groupsV2Operations = capabilities.isGv2() ? new GroupsV2Operations(ClientZkOperations.create(
|
||||
serviceEnvironmentConfig.getSignalServiceConfiguration())) : null;
|
||||
final SleepTimer timer = new UptimeSleepTimer();
|
||||
this.accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
credentialsProvider,
|
||||
userAgent,
|
||||
groupsV2Operations,
|
||||
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
|
||||
this.groupsV2Api = accountManager.getGroupsV2Api();
|
||||
this.keyBackupService = accountManager.getKeyBackupService(ServiceConfig.getIasKeyStore(),
|
||||
serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(),
|
||||
serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(),
|
||||
serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(),
|
||||
10);
|
||||
final ClientZkProfileOperations clientZkProfileOperations = capabilities.isGv2() ? ClientZkOperations.create(
|
||||
serviceEnvironmentConfig.getSignalServiceConfiguration()).getProfileOperations() : null;
|
||||
this.messageReceiver = new SignalServiceMessageReceiver(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
credentialsProvider,
|
||||
userAgent,
|
||||
clientZkProfileOperations,
|
||||
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
|
||||
|
||||
final var healthMonitor = new SignalWebSocketHealthMonitor(timer);
|
||||
final WebSocketFactory webSocketFactory = new WebSocketFactory() {
|
||||
@Override
|
||||
public WebSocketConnection createWebSocket() {
|
||||
return new WebSocketConnection("normal",
|
||||
serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
Optional.of(credentialsProvider),
|
||||
userAgent,
|
||||
healthMonitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketConnection createUnidentifiedWebSocket() {
|
||||
return new WebSocketConnection("unidentified",
|
||||
serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
Optional.absent(),
|
||||
userAgent,
|
||||
healthMonitor);
|
||||
}
|
||||
};
|
||||
this.signalWebSocket = new SignalWebSocket(webSocketFactory);
|
||||
healthMonitor.monitor(signalWebSocket);
|
||||
this.profileService = new ProfileService(clientZkProfileOperations, messageReceiver, signalWebSocket);
|
||||
|
||||
final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.getUnidentifiedSenderTrustRoot());
|
||||
this.cipher = new SignalServiceCipher(selfAddress, dataStore, sessionLock, certificateValidator);
|
||||
this.messageSender = new SignalServiceMessageSender(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
credentialsProvider,
|
||||
dataStore,
|
||||
sessionLock,
|
||||
userAgent,
|
||||
signalWebSocket,
|
||||
Optional.absent(),
|
||||
clientZkProfileOperations,
|
||||
executor,
|
||||
ServiceConfig.MAX_ENVELOPE_SIZE,
|
||||
ServiceConfig.AUTOMATIC_NETWORK_RETRY);
|
||||
this.serviceEnvironmentConfig = serviceEnvironmentConfig;
|
||||
this.userAgent = userAgent;
|
||||
this.credentialsProvider = credentialsProvider;
|
||||
this.dataStore = dataStore;
|
||||
this.executor = executor;
|
||||
this.sessionLock = sessionLock;
|
||||
}
|
||||
|
||||
public SignalServiceAccountManager getAccountManager() {
|
||||
return accountManager;
|
||||
return getOrCreate(() -> accountManager,
|
||||
() -> accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
credentialsProvider,
|
||||
userAgent,
|
||||
getGroupsV2Operations(),
|
||||
ServiceConfig.AUTOMATIC_NETWORK_RETRY));
|
||||
}
|
||||
|
||||
public GroupsV2Api getGroupsV2Api() {
|
||||
return groupsV2Api;
|
||||
return getOrCreate(() -> groupsV2Api, () -> groupsV2Api = getAccountManager().getGroupsV2Api());
|
||||
}
|
||||
|
||||
public GroupsV2Operations getGroupsV2Operations() {
|
||||
return groupsV2Operations;
|
||||
return getOrCreate(() -> groupsV2Operations,
|
||||
() -> groupsV2Operations = capabilities.isGv2() ? new GroupsV2Operations(ClientZkOperations.create(
|
||||
serviceEnvironmentConfig.getSignalServiceConfiguration())) : null);
|
||||
}
|
||||
|
||||
private ClientZkOperations getClientZkOperations() {
|
||||
return getOrCreate(() -> clientZkOperations,
|
||||
() -> clientZkOperations = capabilities.isGv2()
|
||||
? ClientZkOperations.create(serviceEnvironmentConfig.getSignalServiceConfiguration())
|
||||
: null);
|
||||
}
|
||||
|
||||
public SignalWebSocket getSignalWebSocket() {
|
||||
return signalWebSocket;
|
||||
return getOrCreate(() -> signalWebSocket, () -> {
|
||||
final var timer = new UptimeSleepTimer();
|
||||
final var healthMonitor = new SignalWebSocketHealthMonitor(timer);
|
||||
final var webSocketFactory = new WebSocketFactory() {
|
||||
@Override
|
||||
public WebSocketConnection createWebSocket() {
|
||||
return new WebSocketConnection("normal",
|
||||
serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
Optional.of(credentialsProvider),
|
||||
userAgent,
|
||||
healthMonitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebSocketConnection createUnidentifiedWebSocket() {
|
||||
return new WebSocketConnection("unidentified",
|
||||
serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
Optional.absent(),
|
||||
userAgent,
|
||||
healthMonitor);
|
||||
}
|
||||
};
|
||||
signalWebSocket = new SignalWebSocket(webSocketFactory);
|
||||
healthMonitor.monitor(signalWebSocket);
|
||||
});
|
||||
}
|
||||
|
||||
public SignalServiceMessageReceiver getMessageReceiver() {
|
||||
return messageReceiver;
|
||||
return getOrCreate(() -> messageReceiver,
|
||||
() -> messageReceiver = new SignalServiceMessageReceiver(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
credentialsProvider,
|
||||
userAgent,
|
||||
getClientZkOperations().getProfileOperations(),
|
||||
ServiceConfig.AUTOMATIC_NETWORK_RETRY));
|
||||
}
|
||||
|
||||
public SignalServiceMessageSender getMessageSender() {
|
||||
return messageSender;
|
||||
return getOrCreate(() -> messageSender,
|
||||
() -> messageSender = new SignalServiceMessageSender(serviceEnvironmentConfig.getSignalServiceConfiguration(),
|
||||
credentialsProvider,
|
||||
dataStore,
|
||||
sessionLock,
|
||||
userAgent,
|
||||
getSignalWebSocket(),
|
||||
Optional.absent(),
|
||||
getClientZkOperations().getProfileOperations(),
|
||||
executor,
|
||||
ServiceConfig.MAX_ENVELOPE_SIZE,
|
||||
ServiceConfig.AUTOMATIC_NETWORK_RETRY));
|
||||
}
|
||||
|
||||
public KeyBackupService getKeyBackupService() {
|
||||
return keyBackupService;
|
||||
return getOrCreate(() -> keyBackupService,
|
||||
() -> keyBackupService = getAccountManager().getKeyBackupService(ServiceConfig.getIasKeyStore(),
|
||||
serviceEnvironmentConfig.getKeyBackupConfig().getEnclaveName(),
|
||||
serviceEnvironmentConfig.getKeyBackupConfig().getServiceId(),
|
||||
serviceEnvironmentConfig.getKeyBackupConfig().getMrenclave(),
|
||||
10));
|
||||
}
|
||||
|
||||
public ProfileService getProfileService() {
|
||||
return profileService;
|
||||
return getOrCreate(() -> profileService,
|
||||
() -> profileService = new ProfileService(getClientZkOperations().getProfileOperations(),
|
||||
getMessageReceiver(),
|
||||
getSignalWebSocket()));
|
||||
}
|
||||
|
||||
public SignalServiceCipher getCipher() {
|
||||
return cipher;
|
||||
return getOrCreate(() -> cipher, () -> {
|
||||
final var certificateValidator = new CertificateValidator(serviceEnvironmentConfig.getUnidentifiedSenderTrustRoot());
|
||||
final var address = new SignalServiceAddress(credentialsProvider.getUuid(), credentialsProvider.getE164());
|
||||
cipher = new SignalServiceCipher(address, dataStore, sessionLock, certificateValidator);
|
||||
});
|
||||
}
|
||||
|
||||
private <T> T getOrCreate(Supplier<T> supplier, Callable creator) {
|
||||
var value = supplier.get();
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
synchronized (LOCK) {
|
||||
value = supplier.get();
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
creator.call();
|
||||
return supplier.get();
|
||||
}
|
||||
}
|
||||
|
||||
private interface Callable {
|
||||
|
||||
void call();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,28 @@ public final class IncomingMessageHandler {
|
|||
this.jobExecutor = jobExecutor;
|
||||
}
|
||||
|
||||
public Pair<List<HandleAction>, Exception> handleRetryEnvelope(
|
||||
final SignalServiceEnvelope envelope,
|
||||
final boolean ignoreAttachments,
|
||||
final Manager.ReceiveMessageHandler handler
|
||||
) {
|
||||
SignalServiceContent content = null;
|
||||
if (!envelope.isReceipt()) {
|
||||
try {
|
||||
content = dependencies.getCipher().decrypt(envelope);
|
||||
} catch (ProtocolUntrustedIdentityException e) {
|
||||
final var recipientId = account.getRecipientStore().resolveRecipient(e.getSender());
|
||||
final var exception = new UntrustedIdentityException(addressResolver.resolveSignalServiceAddress(
|
||||
recipientId), e.getSenderDevice());
|
||||
return new Pair<>(List.of(), exception);
|
||||
} catch (Exception e) {
|
||||
return new Pair<>(List.of(), e);
|
||||
}
|
||||
}
|
||||
final var actions = checkAndHandleMessage(envelope, content, ignoreAttachments, handler, null);
|
||||
return new Pair<>(actions, null);
|
||||
}
|
||||
|
||||
public Pair<List<HandleAction>, Exception> handleEnvelope(
|
||||
final SignalServiceEnvelope envelope,
|
||||
final boolean ignoreAttachments,
|
||||
|
@ -108,35 +130,48 @@ public final class IncomingMessageHandler {
|
|||
} catch (Exception e) {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
if (!envelope.hasSourceUuid() && content != null) {
|
||||
// Store uuid if we don't have it already
|
||||
// address/uuid is validated by unidentified sender certificate
|
||||
account.getRecipientStore().resolveRecipientTrusted(content.getSender());
|
||||
}
|
||||
}
|
||||
|
||||
actions.addAll(checkAndHandleMessage(envelope, content, ignoreAttachments, handler, exception));
|
||||
return new Pair<>(actions, exception);
|
||||
}
|
||||
|
||||
private List<HandleAction> checkAndHandleMessage(
|
||||
final SignalServiceEnvelope envelope,
|
||||
final SignalServiceContent content,
|
||||
final boolean ignoreAttachments,
|
||||
final Manager.ReceiveMessageHandler handler,
|
||||
final Exception exception
|
||||
) {
|
||||
if (!envelope.hasSourceUuid() && content != null) {
|
||||
// Store uuid if we don't have it already
|
||||
// address/uuid is validated by unidentified sender certificate
|
||||
account.getRecipientStore().resolveRecipientTrusted(content.getSender());
|
||||
}
|
||||
if (isMessageBlocked(envelope, content)) {
|
||||
logger.info("Ignoring a message from blocked user/group: {}", envelope.getTimestamp());
|
||||
return List.of();
|
||||
} else if (isNotAllowedToSendToGroup(envelope, content)) {
|
||||
logger.info("Ignoring a group message from an unauthorized sender (no member or admin): {} {}",
|
||||
(envelope.hasSourceUuid() ? envelope.getSourceAddress() : content.getSender()).getIdentifier(),
|
||||
envelope.getTimestamp());
|
||||
return List.of();
|
||||
} else {
|
||||
actions.addAll(handleMessage(envelope, content, ignoreAttachments));
|
||||
List<HandleAction> actions;
|
||||
if (content != null) {
|
||||
actions = handleMessage(envelope, content, ignoreAttachments);
|
||||
} else {
|
||||
actions = List.of();
|
||||
}
|
||||
handler.handleMessage(envelope, content, exception);
|
||||
return actions;
|
||||
}
|
||||
return new Pair<>(actions, exception);
|
||||
}
|
||||
|
||||
public List<HandleAction> handleMessage(
|
||||
SignalServiceEnvelope envelope, SignalServiceContent content, boolean ignoreAttachments
|
||||
) {
|
||||
var actions = new ArrayList<HandleAction>();
|
||||
if (content == null) {
|
||||
return actions;
|
||||
}
|
||||
|
||||
final RecipientId sender;
|
||||
if (!envelope.isUnidentifiedSender() && envelope.hasSourceUuid()) {
|
||||
sender = recipientResolver.resolveRecipient(envelope.getSourceAddress());
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package org.asamk.signal.manager.helper;
|
||||
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
||||
|
||||
public interface MessageReceiverProvider {
|
||||
|
||||
SignalServiceMessageReceiver getMessageReceiver();
|
||||
}
|
|
@ -45,8 +45,6 @@ public final class ProfileHelper {
|
|||
private final AvatarStore avatarStore;
|
||||
private final ProfileKeyProvider profileKeyProvider;
|
||||
private final UnidentifiedAccessProvider unidentifiedAccessProvider;
|
||||
private final ProfileServiceProvider profileServiceProvider;
|
||||
private final MessageReceiverProvider messageReceiverProvider;
|
||||
private final SignalServiceAddressResolver addressResolver;
|
||||
|
||||
public ProfileHelper(
|
||||
|
@ -55,8 +53,6 @@ public final class ProfileHelper {
|
|||
final AvatarStore avatarStore,
|
||||
final ProfileKeyProvider profileKeyProvider,
|
||||
final UnidentifiedAccessProvider unidentifiedAccessProvider,
|
||||
final ProfileServiceProvider profileServiceProvider,
|
||||
final MessageReceiverProvider messageReceiverProvider,
|
||||
final SignalServiceAddressResolver addressResolver
|
||||
) {
|
||||
this.account = account;
|
||||
|
@ -64,8 +60,6 @@ public final class ProfileHelper {
|
|||
this.avatarStore = avatarStore;
|
||||
this.profileKeyProvider = profileKeyProvider;
|
||||
this.unidentifiedAccessProvider = unidentifiedAccessProvider;
|
||||
this.profileServiceProvider = profileServiceProvider;
|
||||
this.messageReceiverProvider = messageReceiverProvider;
|
||||
this.addressResolver = addressResolver;
|
||||
}
|
||||
|
||||
|
@ -218,7 +212,7 @@ public final class ProfileHelper {
|
|||
}
|
||||
|
||||
private SignalServiceProfile retrieveProfileSync(String username) throws IOException {
|
||||
return messageReceiverProvider.getMessageReceiver().retrieveProfileByUsername(username, Optional.absent());
|
||||
return dependencies.getMessageReceiver().retrieveProfileByUsername(username, Optional.absent());
|
||||
}
|
||||
|
||||
private ProfileAndCredential retrieveProfileAndCredential(
|
||||
|
@ -287,7 +281,7 @@ public final class ProfileHelper {
|
|||
Optional<UnidentifiedAccess> unidentifiedAccess,
|
||||
SignalServiceProfile.RequestType requestType
|
||||
) {
|
||||
var profileService = profileServiceProvider.getProfileService();
|
||||
var profileService = dependencies.getProfileService();
|
||||
|
||||
Single<ServiceResponse<ProfileAndCredential>> responseSingle;
|
||||
try {
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package org.asamk.signal.manager.helper;
|
||||
|
||||
import org.whispersystems.signalservice.api.services.ProfileService;
|
||||
|
||||
public interface ProfileServiceProvider {
|
||||
|
||||
ProfileService getProfileService();
|
||||
}
|
|
@ -222,8 +222,13 @@ public class SyncHelper {
|
|||
try {
|
||||
c = s.read();
|
||||
} catch (IOException e) {
|
||||
logger.warn("Sync contacts contained invalid contact, ignoring: {}", e.getMessage());
|
||||
continue;
|
||||
if (e.getMessage() != null && e.getMessage().contains("Missing contact address!")) {
|
||||
logger.warn("Sync contacts contained invalid contact, ignoring: {}", e.getMessage());
|
||||
continue;
|
||||
} else {
|
||||
logger.warn("Failed to read sync contacts", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (c == null) {
|
||||
break;
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
package org.asamk.signal.manager.jobs;
|
||||
|
||||
import org.asamk.signal.manager.SignalDependencies;
|
||||
import org.asamk.signal.manager.StickerPackStore;
|
||||
import org.asamk.signal.manager.helper.GroupHelper;
|
||||
import org.asamk.signal.manager.helper.ProfileHelper;
|
||||
import org.asamk.signal.manager.helper.SendHelper;
|
||||
import org.asamk.signal.manager.helper.SyncHelper;
|
||||
import org.asamk.signal.manager.storage.SignalAccount;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
||||
|
||||
public class Context {
|
||||
|
||||
private final SignalAccount account;
|
||||
private final SignalServiceAccountManager accountManager;
|
||||
private final SignalServiceMessageReceiver messageReceiver;
|
||||
private final SignalDependencies dependencies;
|
||||
private final StickerPackStore stickerPackStore;
|
||||
private final SendHelper sendHelper;
|
||||
private final GroupHelper groupHelper;
|
||||
|
@ -22,8 +20,7 @@ public class Context {
|
|||
|
||||
public Context(
|
||||
final SignalAccount account,
|
||||
final SignalServiceAccountManager accountManager,
|
||||
final SignalServiceMessageReceiver messageReceiver,
|
||||
final SignalDependencies dependencies,
|
||||
final StickerPackStore stickerPackStore,
|
||||
final SendHelper sendHelper,
|
||||
final GroupHelper groupHelper,
|
||||
|
@ -31,8 +28,7 @@ public class Context {
|
|||
final ProfileHelper profileHelper
|
||||
) {
|
||||
this.account = account;
|
||||
this.accountManager = accountManager;
|
||||
this.messageReceiver = messageReceiver;
|
||||
this.dependencies = dependencies;
|
||||
this.stickerPackStore = stickerPackStore;
|
||||
this.sendHelper = sendHelper;
|
||||
this.groupHelper = groupHelper;
|
||||
|
@ -44,12 +40,8 @@ public class Context {
|
|||
return account;
|
||||
}
|
||||
|
||||
public SignalServiceAccountManager getAccountManager() {
|
||||
return accountManager;
|
||||
}
|
||||
|
||||
public SignalServiceMessageReceiver getMessageReceiver() {
|
||||
return messageReceiver;
|
||||
public SignalDependencies getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
public StickerPackStore getStickerPackStore() {
|
||||
|
|
|
@ -32,7 +32,9 @@ public class RetrieveStickerPackJob implements Job {
|
|||
}
|
||||
logger.debug("Retrieving sticker pack {}.", Hex.toStringCondensed(packId.serialize()));
|
||||
try {
|
||||
final var manifest = context.getMessageReceiver().retrieveStickerManifest(packId.serialize(), packKey);
|
||||
final var manifest = context.getDependencies()
|
||||
.getMessageReceiver()
|
||||
.retrieveStickerManifest(packId.serialize(), packKey);
|
||||
|
||||
final var stickerIds = new HashSet<Integer>();
|
||||
if (manifest.getCover().isPresent()) {
|
||||
|
@ -43,7 +45,9 @@ public class RetrieveStickerPackJob implements Job {
|
|||
}
|
||||
|
||||
for (var id : stickerIds) {
|
||||
final var inputStream = context.getMessageReceiver().retrieveSticker(packId.serialize(), packKey, id);
|
||||
final var inputStream = context.getDependencies()
|
||||
.getMessageReceiver()
|
||||
.retrieveSticker(packId.serialize(), packKey, id);
|
||||
context.getStickerPackStore().storeSticker(packId, id, o -> IOUtils.copyStream(inputStream, o));
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.asamk.signal.manager.storage.protocol.SignalProtocolStore;
|
|||
import org.asamk.signal.manager.storage.recipients.Contact;
|
||||
import org.asamk.signal.manager.storage.recipients.LegacyRecipientStore;
|
||||
import org.asamk.signal.manager.storage.recipients.Profile;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientAddress;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientId;
|
||||
import org.asamk.signal.manager.storage.recipients.RecipientStore;
|
||||
import org.asamk.signal.manager.storage.sessions.SessionStore;
|
||||
|
@ -789,7 +790,7 @@ public class SignalAccount implements Closeable {
|
|||
}
|
||||
|
||||
public RecipientId getSelfRecipientId() {
|
||||
return recipientStore.resolveRecipientTrusted(getSelfAddress());
|
||||
return recipientStore.resolveRecipientTrusted(new RecipientAddress(uuid, username));
|
||||
}
|
||||
|
||||
public String getEncryptedDeviceName() {
|
||||
|
|
|
@ -5,7 +5,7 @@ public class BaseConfig {
|
|||
public final static String PROJECT_NAME = BaseConfig.class.getPackage().getImplementationTitle();
|
||||
public final static String PROJECT_VERSION = BaseConfig.class.getPackage().getImplementationVersion();
|
||||
|
||||
final static String USER_AGENT_SIGNAL_ANDROID = "Signal-Android/5.12.4";
|
||||
final static String USER_AGENT_SIGNAL_ANDROID = "Signal-Android/5.22.3";
|
||||
final static String USER_AGENT_SIGNAL_CLI = PROJECT_NAME == null
|
||||
? "signal-cli"
|
||||
: PROJECT_NAME + "/" + PROJECT_VERSION;
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.whispersystems.libsignal.util.Pair;
|
|||
import org.whispersystems.signalservice.api.KeyBackupServicePinException;
|
||||
import org.whispersystems.signalservice.api.KeyBackupSystemNoDataException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException;
|
||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
@ -99,6 +100,10 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl {
|
|||
public void registerWithCaptcha(
|
||||
final String number, final boolean voiceVerification, final String captcha
|
||||
) throws Error.Failure, Error.InvalidNumber {
|
||||
if (!PhoneNumberFormatter.isValidNumber(number, null)) {
|
||||
throw new SignalControl.Error.InvalidNumber(
|
||||
"Invalid username (phone number), make sure you include the country code.");
|
||||
}
|
||||
try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) {
|
||||
registrationManager.register(voiceVerification, captcha);
|
||||
} catch (CaptchaRequiredException e) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue