diff --git a/graalvm-config-dir/reflect-config.json b/graalvm-config-dir/reflect-config.json index d24416d9ae..401727f6b4 100644 --- a/graalvm-config-dir/reflect-config.json +++ b/graalvm-config-dir/reflect-config.json @@ -1363,6 +1363,10 @@ "name":"org.bouncycastle.jcajce.provider.asymmetric.DSTU4145$Mappings", "methods":[{"name":"","parameterTypes":[] }] }, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.Dilithium$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, { "name":"org.bouncycastle.jcajce.provider.asymmetric.EC$Mappings", "methods":[{"name":"","parameterTypes":[] }] @@ -1371,6 +1375,10 @@ "name":"org.bouncycastle.jcajce.provider.asymmetric.ECGOST$Mappings", "methods":[{"name":"","parameterTypes":[] }] }, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.EXTERNAL$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, { "name":"org.bouncycastle.jcajce.provider.asymmetric.EdEC$Mappings", "methods":[{"name":"","parameterTypes":[] }] @@ -1379,6 +1387,10 @@ "name":"org.bouncycastle.jcajce.provider.asymmetric.ElGamal$Mappings", "methods":[{"name":"","parameterTypes":[] }] }, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.Falcon$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, { "name":"org.bouncycastle.jcajce.provider.asymmetric.GM$Mappings", "methods":[{"name":"","parameterTypes":[] }] @@ -1391,10 +1403,22 @@ "name":"org.bouncycastle.jcajce.provider.asymmetric.IES$Mappings", "methods":[{"name":"","parameterTypes":[] }] }, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.LMS$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.NTRU$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, { "name":"org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings", "methods":[{"name":"","parameterTypes":[] }] }, +{ + "name":"org.bouncycastle.jcajce.provider.asymmetric.SPHINCSPlus$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, { "name":"org.bouncycastle.jcajce.provider.asymmetric.X509$Mappings", "methods":[{"name":"","parameterTypes":[] }] @@ -1419,6 +1443,10 @@ "name":"org.bouncycastle.jcajce.provider.digest.Blake2s$Mappings", "methods":[{"name":"","parameterTypes":[] }] }, +{ + "name":"org.bouncycastle.jcajce.provider.digest.Blake3$Mappings", + "methods":[{"name":"","parameterTypes":[] }] +}, { "name":"org.bouncycastle.jcajce.provider.digest.DSTU7564$Mappings", "methods":[{"name":"","parameterTypes":[] }] diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index defe71558a..41e08fb630 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -92,7 +92,7 @@ static boolean isSignalClientAvailable() { Configuration getConfiguration(); - void updateConfiguration(Configuration configuration) throws IOException, NotPrimaryDeviceException; + void updateConfiguration(Configuration configuration) throws NotPrimaryDeviceException; /** * Update the user's profile. @@ -160,11 +160,11 @@ SendMessageResults sendTypingMessage( SendMessageResults sendReadReceipt( RecipientIdentifier.Single sender, List messageIds - ) throws IOException; + ); SendMessageResults sendViewedReceipt( RecipientIdentifier.Single sender, List messageIds - ) throws IOException; + ); SendMessageResults sendMessage( Message message, Set recipients @@ -199,7 +199,7 @@ SendMessageResults sendPaymentNotificationMessage( void setContactName( RecipientIdentifier.Single recipient, String givenName, final String familyName - ) throws NotPrimaryDeviceException, IOException, UnregisteredRecipientException; + ) throws NotPrimaryDeviceException, UnregisteredRecipientException; void setContactsBlocked( Collection recipient, boolean blocked @@ -299,7 +299,7 @@ boolean trustIdentityVerified( InputStream retrieveAttachment(final String id) throws IOException; @Override - void close() throws IOException; + void close(); interface ReceiveMessageHandler { diff --git a/lib/src/main/java/org/asamk/signal/manager/Settings.java b/lib/src/main/java/org/asamk/signal/manager/Settings.java index 878545141d..5fd4e36bad 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Settings.java +++ b/lib/src/main/java/org/asamk/signal/manager/Settings.java @@ -4,5 +4,5 @@ public record Settings(TrustNewIdentity trustNewIdentity, boolean disableMessageSendLog) { - public static Settings DEFAULT = new Settings(TrustNewIdentity.ON_FIRST_USE, false); + public static final Settings DEFAULT = new Settings(TrustNewIdentity.ON_FIRST_USE, false); } diff --git a/lib/src/main/java/org/asamk/signal/manager/actions/SendRetryMessageRequestAction.java b/lib/src/main/java/org/asamk/signal/manager/actions/SendRetryMessageRequestAction.java index 1975fd1794..865f062f3c 100644 --- a/lib/src/main/java/org/asamk/signal/manager/actions/SendRetryMessageRequestAction.java +++ b/lib/src/main/java/org/asamk/signal/manager/actions/SendRetryMessageRequestAction.java @@ -50,7 +50,9 @@ public void execute(Context context) throws Throwable { envelopeType = messageContent.getType(); } else { originalContent = envelope.getContent(); - envelopeType = envelopeTypeToCiphertextMessageType(envelope.getType()); + envelopeType = envelope.getType() == null + ? CiphertextMessage.WHISPER_TYPE + : envelopeTypeToCiphertextMessageType(envelope.getType()); } DecryptionErrorMessage decryptionErrorMessage = DecryptionErrorMessage.forOriginalMessage(originalContent, diff --git a/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java b/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java index 00abd93e74..f4b6332422 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/MessageEnvelope.java @@ -34,6 +34,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.ViewedMessage; import java.io.File; +import java.io.IOException; import java.util.List; import java.util.Optional; import java.util.Set; @@ -234,7 +235,7 @@ static Quote from( return new Quote(quote.getId(), addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor())) .toApiRecipientAddress(), - Optional.ofNullable(quote.getText()), + Optional.of(quote.getText()), quote.getMentions() == null ? List.of() : quote.getMentions() @@ -291,9 +292,9 @@ public record Attachment( boolean isBorderless ) { - static Attachment from(SignalServiceAttachment attachment, AttachmentFileProvider fileProvider) { - if (attachment.isPointer()) { - final var a = attachment.asPointer(); + static Attachment from(SignalServiceAttachment signalAttachment, AttachmentFileProvider fileProvider) { + if (signalAttachment.isPointer()) { + final var a = signalAttachment.asPointer(); final var attachmentFile = fileProvider.getFile(a); return new Attachment(Optional.of(attachmentFile.getName()), Optional.of(attachmentFile), @@ -310,21 +311,26 @@ static Attachment from(SignalServiceAttachment attachment, AttachmentFileProvide a.isGif(), a.isBorderless()); } else { - final var a = attachment.asStream(); - return new Attachment(Optional.empty(), - Optional.empty(), - a.getFileName(), - a.getContentType(), - a.getUploadTimestamp() == 0 ? Optional.empty() : Optional.of(a.getUploadTimestamp()), - Optional.of(a.getLength()), - a.getPreview(), - Optional.empty(), - a.getCaption(), - a.getWidth() == 0 ? Optional.empty() : Optional.of(a.getWidth()), - a.getHeight() == 0 ? Optional.empty() : Optional.of(a.getHeight()), - a.getVoiceNote(), - a.isGif(), - a.isBorderless()); + Attachment attachment = null; + try (final var a = signalAttachment.asStream()) { + attachment = new Attachment(Optional.empty(), + Optional.empty(), + a.getFileName(), + a.getContentType(), + a.getUploadTimestamp() == 0 ? Optional.empty() : Optional.of(a.getUploadTimestamp()), + Optional.of(a.getLength()), + a.getPreview(), + Optional.empty(), + a.getCaption(), + a.getWidth() == 0 ? Optional.empty() : Optional.of(a.getWidth()), + a.getHeight() == 0 ? Optional.empty() : Optional.of(a.getHeight()), + a.getVoiceNote(), + a.isGif(), + a.isBorderless()); + return attachment; + } catch (IOException e) { + return attachment; + } } } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java index 697786fcd7..5991202e5e 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java @@ -822,8 +822,8 @@ private byte[] readAvatarBytes(final String avatarFile) throws IOException { if (avatarFile == null) { return null; } - try (final var avatar = Utils.createStreamDetails(avatarFile).first().getStream()) { - return IOUtils.readFully(avatar); + try (final var avatar = Utils.createStreamDetails(avatarFile).first()) { + return IOUtils.readFully(avatar.getStream()); } } } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java index c1e22c97b2..b9281889da 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/IdentityHelper.java @@ -14,7 +14,6 @@ import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.push.ServiceId; -import java.io.IOException; import java.util.Arrays; import java.util.function.BiFunction; @@ -112,12 +111,8 @@ private boolean trustIdentity( } account.getIdentityKeyStore().setIdentityTrustLevel(serviceId, identity.getIdentityKey(), trustLevel); - try { - context.getSyncHelper() - .sendVerifiedMessage(address.toSignalServiceAddress(), identity.getIdentityKey(), trustLevel); - } catch (IOException e) { - logger.warn("Failed to send verification sync message: {}", e.getMessage()); - } + context.getSyncHelper() + .sendVerifiedMessage(address.toSignalServiceAddress(), identity.getIdentityKey(), trustLevel); return true; } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java index 6d5f2aa180..1631ad9d37 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java @@ -212,10 +212,11 @@ public void setProfile( if (avatar != null) { if (avatar.isPresent()) { - final var streamDetails = Utils.createStreamDetails(avatar.get()).first(); - context.getAvatarStore() - .storeProfileAvatar(account.getSelfRecipientAddress(), - outputStream -> IOUtils.copyStream(streamDetails.getStream(), outputStream)); + try (final var streamDetails = Utils.createStreamDetails(avatar.get()).first()) { + context.getAvatarStore() + .storeProfileAvatar(account.getSelfRecipientAddress(), + outputStream -> IOUtils.copyStream(streamDetails.getStream(), outputStream)); + } } else { context.getAvatarStore().deleteProfileAvatar(account.getSelfRecipientAddress()); } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/SyncHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/SyncHelper.java index adc4e1d48b..77aa265730 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/SyncHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/SyncHelper.java @@ -13,6 +13,7 @@ import org.signal.libsignal.protocol.IdentityKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream; import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage; @@ -73,8 +74,8 @@ public void requestSyncPniIdentity() { requestSyncData(SyncMessage.Request.Type.PNI_IDENTITY); } - public void sendSyncFetchProfileMessage() { - context.getSendHelper() + public SendMessageResult sendSyncFetchProfileMessage() { + return context.getSendHelper() .sendSyncMessage(SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.LOCAL_PROFILE)); } @@ -193,7 +194,7 @@ public void sendContacts() throws IOException { } } - public void sendBlockedList() { + public SendMessageResult sendBlockedList() { var addresses = new ArrayList(); for (var record : account.getContactStore().getContacts()) { if (record.second().isBlocked()) { @@ -206,30 +207,33 @@ public void sendBlockedList() { groupIds.add(record.getGroupId().serialize()); } } - context.getSendHelper() + return context.getSendHelper() .sendSyncMessage(SignalServiceSyncMessage.forBlocked(new BlockedListMessage(addresses, groupIds))); } - public void sendVerifiedMessage( + public SendMessageResult sendVerifiedMessage( SignalServiceAddress destination, IdentityKey identityKey, TrustLevel trustLevel - ) throws IOException { + ) { var verifiedMessage = new VerifiedMessage(destination, identityKey, trustLevel.toVerifiedState(), System.currentTimeMillis()); - context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forVerified(verifiedMessage)); + return context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forVerified(verifiedMessage)); } - public void sendKeysMessage() { + public SendMessageResult sendKeysMessage() { var keysMessage = new KeysMessage(Optional.ofNullable(account.getStorageKey())); - context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forKeys(keysMessage)); + return context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forKeys(keysMessage)); } - public void sendStickerOperationsMessage(List installStickers, List removeStickers) { + public SendMessageResult sendStickerOperationsMessage( + List installStickers, List removeStickers + ) { var installStickerMessages = installStickers.stream().map(s -> getStickerPackOperationMessage(s, true)); var removeStickerMessages = removeStickers.stream().map(s -> getStickerPackOperationMessage(s, false)); var stickerMessages = Stream.concat(installStickerMessages, removeStickerMessages).toList(); - context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forStickerPackOperations(stickerMessages)); + return context.getSendHelper() + .sendSyncMessage(SignalServiceSyncMessage.forStickerPackOperations(stickerMessages)); } private static StickerPackOperationMessage getStickerPackOperationMessage( @@ -240,13 +244,13 @@ private static StickerPackOperationMessage getStickerPackOperationMessage( installed ? StickerPackOperationMessage.Type.INSTALL : StickerPackOperationMessage.Type.REMOVE); } - public void sendConfigurationMessage() { + public SendMessageResult sendConfigurationMessage() { final var config = account.getConfigurationStore(); var configurationMessage = new ConfigurationMessage(Optional.ofNullable(config.getReadReceipts()), Optional.ofNullable(config.getUnidentifiedDeliveryIndicators()), Optional.ofNullable(config.getTypingIndicators()), Optional.ofNullable(config.getLinkPreviews())); - context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage)); + return context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage)); } public void handleSyncDeviceGroups(final InputStream input) { @@ -344,10 +348,10 @@ public void handleSyncDeviceContacts(final InputStream input) throws IOException } } - private void requestSyncData(final SyncMessage.Request.Type type) { + private SendMessageResult requestSyncData(final SyncMessage.Request.Type type) { var r = new SyncMessage.Request.Builder().type(type).build(); var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); - context.getSendHelper().sendSyncMessage(message); + return context.getSendHelper().sendSyncMessage(message); } private Optional createContactAvatarAttachment(RecipientAddress address) throws IOException { diff --git a/lib/src/main/java/org/asamk/signal/manager/internal/MultiAccountManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/internal/MultiAccountManagerImpl.java index 0461254a42..4dc1ede289 100644 --- a/lib/src/main/java/org/asamk/signal/manager/internal/MultiAccountManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/internal/MultiAccountManagerImpl.java @@ -125,11 +125,7 @@ public RegistrationManager getNewRegistrationManager(String number) throws IOExc public void close() { synchronized (managers) { for (var m : new ArrayList<>(managers)) { - try { - m.close(); - } catch (IOException e) { - logger.warn("Cleanup failed", e); - } + m.close(); } managers.clear(); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/Database.java b/lib/src/main/java/org/asamk/signal/manager/storage/Database.java index 3d0d937402..717046988d 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/Database.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/Database.java @@ -47,7 +47,7 @@ public final Connection getConnection() throws SQLException { } @Override - public void close() throws SQLException { + public void close() { dataSource.close(); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java index 57300b11b4..2d33555d09 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java @@ -1610,11 +1610,7 @@ public void deleteAccountData() throws IOException { public void close() { synchronized (fileChannel) { if (accountDatabase != null) { - try { - accountDatabase.close(); - } catch (SQLException e) { - logger.warn("Failed to close account database: {}", e.getMessage(), e); - } + accountDatabase.close(); } if (messageSendLogStore != null) { messageSendLogStore.close(); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/accounts/AccountsStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/accounts/AccountsStore.java index 0e9fc5fcad..55c5adf093 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/accounts/AccountsStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/accounts/AccountsStore.java @@ -252,18 +252,14 @@ private AccountsStorage readAccountsLocked(FileChannel fileChannel) throws IOExc } private void saveAccountsLocked(FileChannel fileChannel, AccountsStorage accountsStorage) throws IOException { - try { - try (var output = new ByteArrayOutputStream()) { - // Write to memory first to prevent corrupting the file in case of serialization errors - objectMapper.writeValue(output, accountsStorage); - var input = new ByteArrayInputStream(output.toByteArray()); - fileChannel.position(0); - input.transferTo(Channels.newOutputStream(fileChannel)); - fileChannel.truncate(fileChannel.position()); - fileChannel.force(false); - } - } catch (Exception e) { - logger.error("Error saving accounts file: {}", e.getMessage(), e); + try (var output = new ByteArrayOutputStream()) { + // Write to memory first to prevent corrupting the file in case of serialization errors + objectMapper.writeValue(output, accountsStorage); + var input = new ByteArrayInputStream(output.toByteArray()); + fileChannel.position(0); + input.transferTo(Channels.newOutputStream(fileChannel)); + fileChannel.truncate(fileChannel.position()); + fileChannel.force(false); } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyIdentityInfo.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyIdentityInfo.java index 85ebcd2b3c..0d55529104 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyIdentityInfo.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacyIdentityInfo.java @@ -9,9 +9,9 @@ public class LegacyIdentityInfo { RecipientAddress address; - IdentityKey identityKey; - TrustLevel trustLevel; - Date added; + final IdentityKey identityKey; + final TrustLevel trustLevel; + final Date added; LegacyIdentityInfo(RecipientAddress address, IdentityKey identityKey, TrustLevel trustLevel, Date added) { this.address = address; diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacySessionInfo.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacySessionInfo.java index 2cb984fb64..c6097cd9cb 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacySessionInfo.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/LegacySessionInfo.java @@ -4,11 +4,11 @@ public class LegacySessionInfo { - public RecipientAddress address; + public final RecipientAddress address; - public int deviceId; + public final int deviceId; - public byte[] sessionRecord; + public final byte[] sessionRecord; LegacySessionInfo(final RecipientAddress address, final int deviceId, final byte[] sessionRecord) { this.address = address; diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientWithAddress.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientWithAddress.java index 6885a8af06..0fc00113f6 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientWithAddress.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientWithAddress.java @@ -1,3 +1,3 @@ package org.asamk.signal.manager.storage.recipients; -record RecipientWithAddress(RecipientId id, RecipientAddress address) {} +public record RecipientWithAddress(RecipientId id, RecipientAddress address) {} diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java index ebbd87aa6f..b8c0a32256 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java @@ -328,7 +328,7 @@ private Key getKeyFromResultSet(ResultSet resultSet) throws SQLException { return new Key(address, deviceId); } - private SessionRecord getSessionRecordFromResultSet(ResultSet resultSet) throws SQLException { + private SessionRecord getSessionRecordFromResultSet(ResultSet resultSet) { try { final var record = resultSet.getBytes("record"); return new SessionRecord(record); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/threads/LegacyJsonThreadStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/threads/LegacyJsonThreadStore.java index 7e5fd2423b..428e9e9505 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/threads/LegacyJsonThreadStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/threads/LegacyJsonThreadStore.java @@ -25,7 +25,7 @@ public class LegacyJsonThreadStore { @JsonProperty("threads") @JsonSerialize(using = MapToListSerializer.class) @JsonDeserialize(using = ThreadsDeserializer.class) - private Map threads = new HashMap<>(); + private final Map threads = new HashMap<>(); public List getThreads() { return new ArrayList<>(threads.values()); diff --git a/lib/src/main/java/org/asamk/signal/manager/util/MessageCacheUtils.java b/lib/src/main/java/org/asamk/signal/manager/util/MessageCacheUtils.java index b1568bdc21..b3c9457bae 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/MessageCacheUtils.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/MessageCacheUtils.java @@ -69,7 +69,7 @@ public static SignalServiceEnvelope loadEnvelope(File file) throws IOException { if (version >= 2) { serverReceivedTimestamp = in.readLong(); uuid = in.readUTF(); - if ("".equals(uuid)) { + if (uuid.isEmpty()) { uuid = null; } } diff --git a/lib/src/test/java/org/asamk/signal/manager/storage/recipients/MergeRecipientHelperTest.java b/lib/src/test/java/org/asamk/signal/manager/storage/recipients/MergeRecipientHelperTest.java index a617ce93c6..770054f32a 100644 --- a/lib/src/test/java/org/asamk/signal/manager/storage/recipients/MergeRecipientHelperTest.java +++ b/lib/src/test/java/org/asamk/signal/manager/storage/recipients/MergeRecipientHelperTest.java @@ -27,14 +27,14 @@ class MergeRecipientHelperTest { static final PartialAddresses ADDR_A = new PartialAddresses(SERVICE_ID_A, PNI_A, NUMBER_A); static final PartialAddresses ADDR_B = new PartialAddresses(SERVICE_ID_B, PNI_B, NUMBER_B); - static T[] testInstancesNone = new T[]{ + static final T[] testInstancesNone = new T[]{ new T(Set.of(), ADDR_A.FULL, Set.of(rec(1000000, ADDR_A.FULL))), new T(Set.of(), ADDR_A.ACI_NUM, Set.of(rec(1000000, ADDR_A.ACI_NUM))), new T(Set.of(), ADDR_A.ACI_PNI, Set.of(rec(1000000, ADDR_A.ACI_PNI))), new T(Set.of(), ADDR_A.PNI_NUM, Set.of(rec(1000000, ADDR_A.PNI_NUM))), }; - static T[] testInstancesSingle = new T[]{ + static final T[] testInstancesSingle = new T[]{ new T(Set.of(rec(1, ADDR_A.FULL)), ADDR_A.FULL, Set.of(rec(1, ADDR_A.FULL))), new T(Set.of(rec(1, ADDR_A.ACI)), ADDR_A.FULL, Set.of(rec(1, ADDR_A.FULL))), new T(Set.of(rec(1, ADDR_A.PNI)), ADDR_A.FULL, Set.of(rec(1, ADDR_A.FULL))), @@ -74,7 +74,7 @@ class MergeRecipientHelperTest { new T(Set.of(rec(1, ADDR_A.FULL)), ADDR_B.FULL, Set.of(rec(1, ADDR_A.FULL), rec(1000000, ADDR_B.FULL))), }; - static T[] testInstancesTwo = new T[]{ + static final T[] testInstancesTwo = new T[]{ new T(Set.of(rec(1, ADDR_A.ACI), rec(2, ADDR_A.PNI)), ADDR_A.FULL, Set.of(rec(1, ADDR_A.FULL))), new T(Set.of(rec(1, ADDR_A.ACI), rec(2, ADDR_A.NUM)), ADDR_A.FULL, Set.of(rec(1, ADDR_A.FULL))), new T(Set.of(rec(1, ADDR_A.ACI), rec(2, ADDR_A.PNI_NUM)), ADDR_A.FULL, Set.of(rec(1, ADDR_A.FULL))), @@ -100,7 +100,7 @@ class MergeRecipientHelperTest { new T(Set.of(rec(1, ADDR_A.PNI), rec(2, ADDR_A.ACI_NUM)), ADDR_A.ACI_PNI, Set.of(rec(2, ADDR_A.FULL))), }; - static T[] testInstancesThree = new T[]{ + static final T[] testInstancesThree = new T[]{ new T(Set.of(rec(1, ADDR_A.ACI), rec(2, ADDR_A.PNI), rec(3, ADDR_A.NUM)), ADDR_A.FULL, Set.of(rec(1, ADDR_A.FULL))), diff --git a/man/signal-cli-dbus.5.adoc b/man/signal-cli-dbus.5.adoc index 1f2caa1812..cd73b9f089 100644 --- a/man/signal-cli-dbus.5.adoc +++ b/man/signal-cli-dbus.5.adoc @@ -68,9 +68,10 @@ This can be piped to a QR encoder to create a display that can be captured by a For example: -``` +[source] +---- dbus-send --session --dest=org.asamk.Signal --type=method_call --print-reply /org/asamk/Signal org.asamk.Signal.link string:"My secondary client" | tr '\n' '\0' | sed 's/.*string //g' | sed 's/\"//g' | qrencode -s10 -tANSI256 -``` +---- listAccounts() -> accountList:: * accountList : Array of all attached accounts in DBus object path form diff --git a/src/main/java/org/asamk/Signal.java b/src/main/java/org/asamk/Signal.java index c4e3a26ef2..1fab81029d 100644 --- a/src/main/java/org/asamk/Signal.java +++ b/src/main/java/org/asamk/Signal.java @@ -138,9 +138,9 @@ byte[] updateGroup( DBusPath getDevice(long deviceId); - public DBusPath getIdentity(String number); + DBusPath getIdentity(String number); - public List listIdentities(); + List listIdentities(); List listDevices() throws Error.Failure; @@ -497,13 +497,13 @@ public Map> getExtras() { class StructDevice extends Struct { @Position(0) - DBusPath objectPath; + final DBusPath objectPath; @Position(1) - Long id; + final Long id; @Position(2) - String name; + final String name; public StructDevice(final DBusPath objectPath, final Long id, final String name) { this.objectPath = objectPath; @@ -542,13 +542,13 @@ interface Configuration extends DBusInterface, Properties {} class StructGroup extends Struct { @Position(0) - DBusPath objectPath; + final DBusPath objectPath; @Position(1) - byte[] id; + final byte[] id; @Position(2) - String name; + final String name; public StructGroup(final DBusPath objectPath, final byte[] id, final String name) { this.objectPath = objectPath; @@ -610,13 +610,13 @@ interface Group extends DBusInterface, Properties { class StructIdentity extends Struct { @Position(0) - DBusPath objectPath; + final DBusPath objectPath; @Position(1) - String uuid; + final String uuid; @Position(2) - String number; + final String number; public StructIdentity(final DBusPath objectPath, final String uuid, final String number) { this.objectPath = objectPath; diff --git a/src/main/java/org/asamk/signal/App.java b/src/main/java/org/asamk/signal/App.java index 9ac4b19081..f0ebbfaea4 100644 --- a/src/main/java/org/asamk/signal/App.java +++ b/src/main/java/org/asamk/signal/App.java @@ -165,20 +165,7 @@ private void handleCommand( return; } - Set accounts; - try { - accounts = signalAccountFiles.getAllLocalAccountNumbers(); - } catch (IOException e) { - throw new IOErrorException("Failed to load local accounts file", e); - } - if (accounts.size() == 0) { - throw new UserErrorException("No local users found, you first need to register or link an account"); - } else if (accounts.size() > 1) { - throw new UserErrorException( - "Multiple users found, you need to specify an account (phone number) with -a"); - } - - account = accounts.stream().findFirst().get(); + account = getAccountIfOnlyOne(signalAccountFiles); } else if (!Manager.isValidNumber(account, null)) { throw new UserErrorException("Invalid account (phone number), make sure you include the country code."); } @@ -196,6 +183,21 @@ private void handleCommand( throw new UserErrorException("Command only works in multi-account mode"); } + private static String getAccountIfOnlyOne(final SignalAccountFiles signalAccountFiles) throws IOErrorException, UserErrorException { + Set accounts; + try { + accounts = signalAccountFiles.getAllLocalAccountNumbers(); + } catch (IOException e) { + throw new IOErrorException("Failed to load local accounts file", e); + } + if (accounts.isEmpty()) { + throw new UserErrorException("No local users found, you first need to register or link an account"); + } else if (accounts.size() > 1) { + throw new UserErrorException("Multiple users found, you need to specify an account (phone number) with -a"); + } + return accounts.stream().findFirst().get(); + } + private OutputWriter getOutputWriter(final Command command) throws UserErrorException { final var outputTypeInput = ns.get("output"); final var outputType = outputTypeInput == null ? command.getSupportedOutputTypes() @@ -274,8 +276,6 @@ private void handleLocalCommand( ) throws CommandException { try (var m = loadManager(account, signalAccountFiles)) { commandHandler.handleLocalCommand(command, m); - } catch (IOException e) { - logger.warn("Cleanup failed", e); } } diff --git a/src/main/java/org/asamk/signal/commands/SendReceiptCommand.java b/src/main/java/org/asamk/signal/commands/SendReceiptCommand.java index 1eec6c9947..adae7c4d97 100644 --- a/src/main/java/org/asamk/signal/commands/SendReceiptCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendReceiptCommand.java @@ -10,8 +10,6 @@ import org.asamk.signal.output.OutputWriter; import org.asamk.signal.util.CommandUtil; -import java.io.IOException; - import static org.asamk.signal.util.SendMessageResultUtils.outputResult; public class SendReceiptCommand implements JsonRpcLocalCommand { @@ -45,19 +43,14 @@ public void handleCommand( final var targetTimestamps = ns.getList("target-timestamp"); final var type = ns.getString("type"); - try { - final SendMessageResults results; - if (type == null || "read".equals(type)) { - results = m.sendReadReceipt(recipient, targetTimestamps); - } else if ("viewed".equals(type)) { - results = m.sendViewedReceipt(recipient, targetTimestamps); - } else { - throw new UserErrorException("Unknown receipt type: " + type); - } - outputResult(outputWriter, results); - } catch (IOException e) { - throw new UserErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass() - .getSimpleName() + ")"); + final SendMessageResults results; + if (type == null || "read".equals(type)) { + results = m.sendReadReceipt(recipient, targetTimestamps); + } else if ("viewed".equals(type)) { + results = m.sendViewedReceipt(recipient, targetTimestamps); + } else { + throw new UserErrorException("Unknown receipt type: " + type); } + outputResult(outputWriter, results); } } diff --git a/src/main/java/org/asamk/signal/commands/UpdateConfigurationCommand.java b/src/main/java/org/asamk/signal/commands/UpdateConfigurationCommand.java index 73bac05697..d1feff8a9d 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateConfigurationCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateConfigurationCommand.java @@ -4,14 +4,12 @@ import net.sourceforge.argparse4j.inf.Subparser; import org.asamk.signal.commands.exceptions.CommandException; -import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.api.Configuration; import org.asamk.signal.manager.api.NotPrimaryDeviceException; import org.asamk.signal.output.OutputWriter; -import java.io.IOException; import java.util.Optional; public class UpdateConfigurationCommand implements JsonRpcLocalCommand { @@ -51,8 +49,6 @@ public void handleCommand( Optional.ofNullable(unidentifiedDeliveryIndicators), Optional.ofNullable(typingIndicators), Optional.ofNullable(linkPreviews))); - } catch (IOException e) { - throw new IOErrorException("UpdateAccount error: " + e.getMessage(), e); } catch (NotPrimaryDeviceException e) { throw new UserErrorException("This command doesn't work on linked devices."); } diff --git a/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java b/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java index 290ab647f0..49aa0e2777 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java @@ -136,7 +136,7 @@ public Configuration getConfiguration() { } @Override - public void updateConfiguration(Configuration newConfiguration) throws IOException { + public void updateConfiguration(Configuration newConfiguration) { final var configuration = getRemoteObject(new DBusPath(signal.getObjectPath() + "/Configuration"), Signal.Configuration.class); newConfiguration.readReceipts() diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index 2223c96a6d..95acd2cba0 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -351,26 +351,16 @@ public void sendTyping( public void sendReadReceipt( final String recipient, final List messageIds ) throws Error.Failure, Error.UntrustedIdentity { - try { - final var results = m.sendReadReceipt(getSingleRecipientIdentifier(recipient, m.getSelfNumber()), - messageIds); - checkSendMessageResults(results); - } catch (IOException e) { - throw new Error.Failure(e.getMessage()); - } + final var results = m.sendReadReceipt(getSingleRecipientIdentifier(recipient, m.getSelfNumber()), messageIds); + checkSendMessageResults(results); } @Override public void sendViewedReceipt( final String recipient, final List messageIds ) throws Error.Failure, Error.UntrustedIdentity { - try { - final var results = m.sendViewedReceipt(getSingleRecipientIdentifier(recipient, m.getSelfNumber()), - messageIds); - checkSendMessageResults(results); - } catch (IOException e) { - throw new Error.Failure(e.getMessage()); - } + final var results = m.sendViewedReceipt(getSingleRecipientIdentifier(recipient, m.getSelfNumber()), messageIds); + checkSendMessageResults(results); } @Override @@ -532,8 +522,6 @@ public void setContactName(final String number, final String name) { m.setContactName(getSingleRecipientIdentifier(number, m.getSelfNumber()), name, ""); } catch (NotPrimaryDeviceException e) { throw new Error.Failure("This command doesn't work on linked devices."); - } catch (IOException e) { - throw new Error.Failure("Contact is not registered."); } catch (UnregisteredRecipientException e) { throw new Error.UntrustedIdentity(e.getSender().getIdentifier() + " is not registered."); } @@ -1238,8 +1226,6 @@ private void setConfiguration( Optional.ofNullable(unidentifiedDeliveryIndicators), Optional.ofNullable(typingIndicators), Optional.ofNullable(linkPreviews))); - } catch (IOException e) { - throw new Error.Failure("UpdateAccount error: " + e.getMessage()); } catch (NotPrimaryDeviceException e) { throw new Error.Failure("This command doesn't work on linked devices."); }