Fix inspections

This commit is contained in:
AsamK 2023-10-17 20:00:47 +02:00
parent d51dd7ae57
commit fc2e9bbfae
27 changed files with 158 additions and 158 deletions

View file

@ -1363,6 +1363,10 @@
"name":"org.bouncycastle.jcajce.provider.asymmetric.DSTU4145$Mappings", "name":"org.bouncycastle.jcajce.provider.asymmetric.DSTU4145$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }] "methods":[{"name":"<init>","parameterTypes":[] }]
}, },
{
"name":"org.bouncycastle.jcajce.provider.asymmetric.Dilithium$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{ {
"name":"org.bouncycastle.jcajce.provider.asymmetric.EC$Mappings", "name":"org.bouncycastle.jcajce.provider.asymmetric.EC$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }] "methods":[{"name":"<init>","parameterTypes":[] }]
@ -1371,6 +1375,10 @@
"name":"org.bouncycastle.jcajce.provider.asymmetric.ECGOST$Mappings", "name":"org.bouncycastle.jcajce.provider.asymmetric.ECGOST$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }] "methods":[{"name":"<init>","parameterTypes":[] }]
}, },
{
"name":"org.bouncycastle.jcajce.provider.asymmetric.EXTERNAL$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{ {
"name":"org.bouncycastle.jcajce.provider.asymmetric.EdEC$Mappings", "name":"org.bouncycastle.jcajce.provider.asymmetric.EdEC$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }] "methods":[{"name":"<init>","parameterTypes":[] }]
@ -1379,6 +1387,10 @@
"name":"org.bouncycastle.jcajce.provider.asymmetric.ElGamal$Mappings", "name":"org.bouncycastle.jcajce.provider.asymmetric.ElGamal$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }] "methods":[{"name":"<init>","parameterTypes":[] }]
}, },
{
"name":"org.bouncycastle.jcajce.provider.asymmetric.Falcon$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{ {
"name":"org.bouncycastle.jcajce.provider.asymmetric.GM$Mappings", "name":"org.bouncycastle.jcajce.provider.asymmetric.GM$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }] "methods":[{"name":"<init>","parameterTypes":[] }]
@ -1391,10 +1403,22 @@
"name":"org.bouncycastle.jcajce.provider.asymmetric.IES$Mappings", "name":"org.bouncycastle.jcajce.provider.asymmetric.IES$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }] "methods":[{"name":"<init>","parameterTypes":[] }]
}, },
{
"name":"org.bouncycastle.jcajce.provider.asymmetric.LMS$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"org.bouncycastle.jcajce.provider.asymmetric.NTRU$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{ {
"name":"org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings", "name":"org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }] "methods":[{"name":"<init>","parameterTypes":[] }]
}, },
{
"name":"org.bouncycastle.jcajce.provider.asymmetric.SPHINCSPlus$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{ {
"name":"org.bouncycastle.jcajce.provider.asymmetric.X509$Mappings", "name":"org.bouncycastle.jcajce.provider.asymmetric.X509$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }] "methods":[{"name":"<init>","parameterTypes":[] }]
@ -1419,6 +1443,10 @@
"name":"org.bouncycastle.jcajce.provider.digest.Blake2s$Mappings", "name":"org.bouncycastle.jcajce.provider.digest.Blake2s$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }] "methods":[{"name":"<init>","parameterTypes":[] }]
}, },
{
"name":"org.bouncycastle.jcajce.provider.digest.Blake3$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{ {
"name":"org.bouncycastle.jcajce.provider.digest.DSTU7564$Mappings", "name":"org.bouncycastle.jcajce.provider.digest.DSTU7564$Mappings",
"methods":[{"name":"<init>","parameterTypes":[] }] "methods":[{"name":"<init>","parameterTypes":[] }]

View file

@ -92,7 +92,7 @@ public interface Manager extends Closeable {
Configuration getConfiguration(); Configuration getConfiguration();
void updateConfiguration(Configuration configuration) throws IOException, NotPrimaryDeviceException; void updateConfiguration(Configuration configuration) throws NotPrimaryDeviceException;
/** /**
* Update the user's profile. * Update the user's profile.
@ -160,11 +160,11 @@ public interface Manager extends Closeable {
SendMessageResults sendReadReceipt( SendMessageResults sendReadReceipt(
RecipientIdentifier.Single sender, List<Long> messageIds RecipientIdentifier.Single sender, List<Long> messageIds
) throws IOException; );
SendMessageResults sendViewedReceipt( SendMessageResults sendViewedReceipt(
RecipientIdentifier.Single sender, List<Long> messageIds RecipientIdentifier.Single sender, List<Long> messageIds
) throws IOException; );
SendMessageResults sendMessage( SendMessageResults sendMessage(
Message message, Set<RecipientIdentifier> recipients Message message, Set<RecipientIdentifier> recipients
@ -199,7 +199,7 @@ public interface Manager extends Closeable {
void setContactName( void setContactName(
RecipientIdentifier.Single recipient, String givenName, final String familyName RecipientIdentifier.Single recipient, String givenName, final String familyName
) throws NotPrimaryDeviceException, IOException, UnregisteredRecipientException; ) throws NotPrimaryDeviceException, UnregisteredRecipientException;
void setContactsBlocked( void setContactsBlocked(
Collection<RecipientIdentifier.Single> recipient, boolean blocked Collection<RecipientIdentifier.Single> recipient, boolean blocked
@ -299,7 +299,7 @@ public interface Manager extends Closeable {
InputStream retrieveAttachment(final String id) throws IOException; InputStream retrieveAttachment(final String id) throws IOException;
@Override @Override
void close() throws IOException; void close();
interface ReceiveMessageHandler { interface ReceiveMessageHandler {

View file

@ -4,5 +4,5 @@ import org.asamk.signal.manager.api.TrustNewIdentity;
public record Settings(TrustNewIdentity trustNewIdentity, boolean disableMessageSendLog) { 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);
} }

View file

@ -50,7 +50,9 @@ public class SendRetryMessageRequestAction implements HandleAction {
envelopeType = messageContent.getType(); envelopeType = messageContent.getType();
} else { } else {
originalContent = envelope.getContent(); originalContent = envelope.getContent();
envelopeType = envelopeTypeToCiphertextMessageType(envelope.getType()); envelopeType = envelope.getType() == null
? CiphertextMessage.WHISPER_TYPE
: envelopeTypeToCiphertextMessageType(envelope.getType());
} }
DecryptionErrorMessage decryptionErrorMessage = DecryptionErrorMessage.forOriginalMessage(originalContent, DecryptionErrorMessage decryptionErrorMessage = DecryptionErrorMessage.forOriginalMessage(originalContent,

View file

@ -34,6 +34,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.ViewOnceOpenMes
import org.whispersystems.signalservice.api.messages.multidevice.ViewedMessage; import org.whispersystems.signalservice.api.messages.multidevice.ViewedMessage;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
@ -234,7 +235,7 @@ public record MessageEnvelope(
return new Quote(quote.getId(), return new Quote(quote.getId(),
addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor())) addressResolver.resolveRecipientAddress(recipientResolver.resolveRecipient(quote.getAuthor()))
.toApiRecipientAddress(), .toApiRecipientAddress(),
Optional.ofNullable(quote.getText()), Optional.of(quote.getText()),
quote.getMentions() == null quote.getMentions() == null
? List.of() ? List.of()
: quote.getMentions() : quote.getMentions()
@ -291,9 +292,9 @@ public record MessageEnvelope(
boolean isBorderless boolean isBorderless
) { ) {
static Attachment from(SignalServiceAttachment attachment, AttachmentFileProvider fileProvider) { static Attachment from(SignalServiceAttachment signalAttachment, AttachmentFileProvider fileProvider) {
if (attachment.isPointer()) { if (signalAttachment.isPointer()) {
final var a = attachment.asPointer(); final var a = signalAttachment.asPointer();
final var attachmentFile = fileProvider.getFile(a); final var attachmentFile = fileProvider.getFile(a);
return new Attachment(Optional.of(attachmentFile.getName()), return new Attachment(Optional.of(attachmentFile.getName()),
Optional.of(attachmentFile), Optional.of(attachmentFile),
@ -310,21 +311,26 @@ public record MessageEnvelope(
a.isGif(), a.isGif(),
a.isBorderless()); a.isBorderless());
} else { } else {
final var a = attachment.asStream(); Attachment attachment = null;
return new Attachment(Optional.empty(), try (final var a = signalAttachment.asStream()) {
Optional.empty(), attachment = new Attachment(Optional.empty(),
a.getFileName(), Optional.empty(),
a.getContentType(), a.getFileName(),
a.getUploadTimestamp() == 0 ? Optional.empty() : Optional.of(a.getUploadTimestamp()), a.getContentType(),
Optional.of(a.getLength()), a.getUploadTimestamp() == 0 ? Optional.empty() : Optional.of(a.getUploadTimestamp()),
a.getPreview(), Optional.of(a.getLength()),
Optional.empty(), a.getPreview(),
a.getCaption(), Optional.empty(),
a.getWidth() == 0 ? Optional.empty() : Optional.of(a.getWidth()), a.getCaption(),
a.getHeight() == 0 ? Optional.empty() : Optional.of(a.getHeight()), a.getWidth() == 0 ? Optional.empty() : Optional.of(a.getWidth()),
a.getVoiceNote(), a.getHeight() == 0 ? Optional.empty() : Optional.of(a.getHeight()),
a.isGif(), a.getVoiceNote(),
a.isBorderless()); a.isGif(),
a.isBorderless());
return attachment;
} catch (IOException e) {
return attachment;
}
} }
} }

View file

@ -822,8 +822,8 @@ public class GroupHelper {
if (avatarFile == null) { if (avatarFile == null) {
return null; return null;
} }
try (final var avatar = Utils.createStreamDetails(avatarFile).first().getStream()) { try (final var avatar = Utils.createStreamDetails(avatarFile).first()) {
return IOUtils.readFully(avatar); return IOUtils.readFully(avatar.getStream());
} }
} }
} }

View file

@ -14,7 +14,6 @@ import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SendMessageResult;
import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.function.BiFunction; import java.util.function.BiFunction;
@ -112,12 +111,8 @@ public class IdentityHelper {
} }
account.getIdentityKeyStore().setIdentityTrustLevel(serviceId, identity.getIdentityKey(), trustLevel); account.getIdentityKeyStore().setIdentityTrustLevel(serviceId, identity.getIdentityKey(), trustLevel);
try { context.getSyncHelper()
context.getSyncHelper() .sendVerifiedMessage(address.toSignalServiceAddress(), identity.getIdentityKey(), trustLevel);
.sendVerifiedMessage(address.toSignalServiceAddress(), identity.getIdentityKey(), trustLevel);
} catch (IOException e) {
logger.warn("Failed to send verification sync message: {}", e.getMessage());
}
return true; return true;
} }

View file

@ -212,10 +212,11 @@ public final class ProfileHelper {
if (avatar != null) { if (avatar != null) {
if (avatar.isPresent()) { if (avatar.isPresent()) {
final var streamDetails = Utils.createStreamDetails(avatar.get()).first(); try (final var streamDetails = Utils.createStreamDetails(avatar.get()).first()) {
context.getAvatarStore() context.getAvatarStore()
.storeProfileAvatar(account.getSelfRecipientAddress(), .storeProfileAvatar(account.getSelfRecipientAddress(),
outputStream -> IOUtils.copyStream(streamDetails.getStream(), outputStream)); outputStream -> IOUtils.copyStream(streamDetails.getStream(), outputStream));
}
} else { } else {
context.getAvatarStore().deleteProfileAvatar(account.getSelfRecipientAddress()); context.getAvatarStore().deleteProfileAvatar(account.getSelfRecipientAddress());
} }

View file

@ -13,6 +13,7 @@ import org.asamk.signal.manager.util.MimeUtils;
import org.signal.libsignal.protocol.IdentityKey; import org.signal.libsignal.protocol.IdentityKey;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.messages.SendMessageResult;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage; import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage;
@ -73,8 +74,8 @@ public class SyncHelper {
requestSyncData(SyncMessage.Request.Type.PNI_IDENTITY); requestSyncData(SyncMessage.Request.Type.PNI_IDENTITY);
} }
public void sendSyncFetchProfileMessage() { public SendMessageResult sendSyncFetchProfileMessage() {
context.getSendHelper() return context.getSendHelper()
.sendSyncMessage(SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.LOCAL_PROFILE)); .sendSyncMessage(SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.LOCAL_PROFILE));
} }
@ -193,7 +194,7 @@ public class SyncHelper {
} }
} }
public void sendBlockedList() { public SendMessageResult sendBlockedList() {
var addresses = new ArrayList<SignalServiceAddress>(); var addresses = new ArrayList<SignalServiceAddress>();
for (var record : account.getContactStore().getContacts()) { for (var record : account.getContactStore().getContacts()) {
if (record.second().isBlocked()) { if (record.second().isBlocked()) {
@ -206,30 +207,33 @@ public class SyncHelper {
groupIds.add(record.getGroupId().serialize()); groupIds.add(record.getGroupId().serialize());
} }
} }
context.getSendHelper() return context.getSendHelper()
.sendSyncMessage(SignalServiceSyncMessage.forBlocked(new BlockedListMessage(addresses, groupIds))); .sendSyncMessage(SignalServiceSyncMessage.forBlocked(new BlockedListMessage(addresses, groupIds)));
} }
public void sendVerifiedMessage( public SendMessageResult sendVerifiedMessage(
SignalServiceAddress destination, IdentityKey identityKey, TrustLevel trustLevel SignalServiceAddress destination, IdentityKey identityKey, TrustLevel trustLevel
) throws IOException { ) {
var verifiedMessage = new VerifiedMessage(destination, var verifiedMessage = new VerifiedMessage(destination,
identityKey, identityKey,
trustLevel.toVerifiedState(), trustLevel.toVerifiedState(),
System.currentTimeMillis()); 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())); 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<StickerPack> installStickers, List<StickerPack> removeStickers) { public SendMessageResult sendStickerOperationsMessage(
List<StickerPack> installStickers, List<StickerPack> removeStickers
) {
var installStickerMessages = installStickers.stream().map(s -> getStickerPackOperationMessage(s, true)); var installStickerMessages = installStickers.stream().map(s -> getStickerPackOperationMessage(s, true));
var removeStickerMessages = removeStickers.stream().map(s -> getStickerPackOperationMessage(s, false)); var removeStickerMessages = removeStickers.stream().map(s -> getStickerPackOperationMessage(s, false));
var stickerMessages = Stream.concat(installStickerMessages, removeStickerMessages).toList(); var stickerMessages = Stream.concat(installStickerMessages, removeStickerMessages).toList();
context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forStickerPackOperations(stickerMessages)); return context.getSendHelper()
.sendSyncMessage(SignalServiceSyncMessage.forStickerPackOperations(stickerMessages));
} }
private static StickerPackOperationMessage getStickerPackOperationMessage( private static StickerPackOperationMessage getStickerPackOperationMessage(
@ -240,13 +244,13 @@ public class SyncHelper {
installed ? StickerPackOperationMessage.Type.INSTALL : StickerPackOperationMessage.Type.REMOVE); installed ? StickerPackOperationMessage.Type.INSTALL : StickerPackOperationMessage.Type.REMOVE);
} }
public void sendConfigurationMessage() { public SendMessageResult sendConfigurationMessage() {
final var config = account.getConfigurationStore(); final var config = account.getConfigurationStore();
var configurationMessage = new ConfigurationMessage(Optional.ofNullable(config.getReadReceipts()), var configurationMessage = new ConfigurationMessage(Optional.ofNullable(config.getReadReceipts()),
Optional.ofNullable(config.getUnidentifiedDeliveryIndicators()), Optional.ofNullable(config.getUnidentifiedDeliveryIndicators()),
Optional.ofNullable(config.getTypingIndicators()), Optional.ofNullable(config.getTypingIndicators()),
Optional.ofNullable(config.getLinkPreviews())); Optional.ofNullable(config.getLinkPreviews()));
context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage)); return context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage));
} }
public void handleSyncDeviceGroups(final InputStream input) { public void handleSyncDeviceGroups(final InputStream input) {
@ -344,10 +348,10 @@ public class SyncHelper {
} }
} }
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 r = new SyncMessage.Request.Builder().type(type).build();
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
context.getSendHelper().sendSyncMessage(message); return context.getSendHelper().sendSyncMessage(message);
} }
private Optional<SignalServiceAttachmentStream> createContactAvatarAttachment(RecipientAddress address) throws IOException { private Optional<SignalServiceAttachmentStream> createContactAvatarAttachment(RecipientAddress address) throws IOException {

View file

@ -125,11 +125,7 @@ public class MultiAccountManagerImpl implements MultiAccountManager {
public void close() { public void close() {
synchronized (managers) { synchronized (managers) {
for (var m : new ArrayList<>(managers)) { for (var m : new ArrayList<>(managers)) {
try { m.close();
m.close();
} catch (IOException e) {
logger.warn("Cleanup failed", e);
}
} }
managers.clear(); managers.clear();
} }

View file

@ -47,7 +47,7 @@ public abstract class Database implements AutoCloseable {
} }
@Override @Override
public void close() throws SQLException { public void close() {
dataSource.close(); dataSource.close();
} }

View file

@ -1610,11 +1610,7 @@ public class SignalAccount implements Closeable {
public void close() { public void close() {
synchronized (fileChannel) { synchronized (fileChannel) {
if (accountDatabase != null) { if (accountDatabase != null) {
try { accountDatabase.close();
accountDatabase.close();
} catch (SQLException e) {
logger.warn("Failed to close account database: {}", e.getMessage(), e);
}
} }
if (messageSendLogStore != null) { if (messageSendLogStore != null) {
messageSendLogStore.close(); messageSendLogStore.close();

View file

@ -252,18 +252,14 @@ public class AccountsStore {
} }
private void saveAccountsLocked(FileChannel fileChannel, AccountsStorage accountsStorage) throws IOException { private void saveAccountsLocked(FileChannel fileChannel, AccountsStorage accountsStorage) throws IOException {
try { try (var output = new ByteArrayOutputStream()) {
try (var output = new ByteArrayOutputStream()) { // Write to memory first to prevent corrupting the file in case of serialization errors
// Write to memory first to prevent corrupting the file in case of serialization errors objectMapper.writeValue(output, accountsStorage);
objectMapper.writeValue(output, accountsStorage); var input = new ByteArrayInputStream(output.toByteArray());
var input = new ByteArrayInputStream(output.toByteArray()); fileChannel.position(0);
fileChannel.position(0); input.transferTo(Channels.newOutputStream(fileChannel));
input.transferTo(Channels.newOutputStream(fileChannel)); fileChannel.truncate(fileChannel.position());
fileChannel.truncate(fileChannel.position()); fileChannel.force(false);
fileChannel.force(false);
}
} catch (Exception e) {
logger.error("Error saving accounts file: {}", e.getMessage(), e);
} }
} }

View file

@ -9,9 +9,9 @@ import java.util.Date;
public class LegacyIdentityInfo { public class LegacyIdentityInfo {
RecipientAddress address; RecipientAddress address;
IdentityKey identityKey; final IdentityKey identityKey;
TrustLevel trustLevel; final TrustLevel trustLevel;
Date added; final Date added;
LegacyIdentityInfo(RecipientAddress address, IdentityKey identityKey, TrustLevel trustLevel, Date added) { LegacyIdentityInfo(RecipientAddress address, IdentityKey identityKey, TrustLevel trustLevel, Date added) {
this.address = address; this.address = address;

View file

@ -4,11 +4,11 @@ import org.asamk.signal.manager.storage.recipients.RecipientAddress;
public class LegacySessionInfo { 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) { LegacySessionInfo(final RecipientAddress address, final int deviceId, final byte[] sessionRecord) {
this.address = address; this.address = address;

View file

@ -1,3 +1,3 @@
package org.asamk.signal.manager.storage.recipients; package org.asamk.signal.manager.storage.recipients;
record RecipientWithAddress(RecipientId id, RecipientAddress address) {} public record RecipientWithAddress(RecipientId id, RecipientAddress address) {}

View file

@ -328,7 +328,7 @@ public class SessionStore implements SignalServiceSessionStore {
return new Key(address, deviceId); return new Key(address, deviceId);
} }
private SessionRecord getSessionRecordFromResultSet(ResultSet resultSet) throws SQLException { private SessionRecord getSessionRecordFromResultSet(ResultSet resultSet) {
try { try {
final var record = resultSet.getBytes("record"); final var record = resultSet.getBytes("record");
return new SessionRecord(record); return new SessionRecord(record);

View file

@ -25,7 +25,7 @@ public class LegacyJsonThreadStore {
@JsonProperty("threads") @JsonProperty("threads")
@JsonSerialize(using = MapToListSerializer.class) @JsonSerialize(using = MapToListSerializer.class)
@JsonDeserialize(using = ThreadsDeserializer.class) @JsonDeserialize(using = ThreadsDeserializer.class)
private Map<String, LegacyThreadInfo> threads = new HashMap<>(); private final Map<String, LegacyThreadInfo> threads = new HashMap<>();
public List<LegacyThreadInfo> getThreads() { public List<LegacyThreadInfo> getThreads() {
return new ArrayList<>(threads.values()); return new ArrayList<>(threads.values());

View file

@ -69,7 +69,7 @@ public class MessageCacheUtils {
if (version >= 2) { if (version >= 2) {
serverReceivedTimestamp = in.readLong(); serverReceivedTimestamp = in.readLong();
uuid = in.readUTF(); uuid = in.readUTF();
if ("".equals(uuid)) { if (uuid.isEmpty()) {
uuid = null; uuid = null;
} }
} }

View file

@ -27,14 +27,14 @@ class MergeRecipientHelperTest {
static final PartialAddresses ADDR_A = new PartialAddresses(SERVICE_ID_A, PNI_A, NUMBER_A); 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 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.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_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.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))), 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.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.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))), 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))), 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.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.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))), 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))), 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)), new T(Set.of(rec(1, ADDR_A.ACI), rec(2, ADDR_A.PNI), rec(3, ADDR_A.NUM)),
ADDR_A.FULL, ADDR_A.FULL,
Set.of(rec(1, ADDR_A.FULL))), Set.of(rec(1, ADDR_A.FULL))),

View file

@ -68,9 +68,10 @@ This can be piped to a QR encoder to create a display that can be captured by a
For example: 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 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<as>:: listAccounts() -> accountList<as>::
* accountList : Array of all attached accounts in DBus object path form * accountList : Array of all attached accounts in DBus object path form

View file

@ -138,9 +138,9 @@ public interface Signal extends DBusInterface {
DBusPath getDevice(long deviceId); DBusPath getDevice(long deviceId);
public DBusPath getIdentity(String number); DBusPath getIdentity(String number);
public List<StructIdentity> listIdentities(); List<StructIdentity> listIdentities();
List<StructDevice> listDevices() throws Error.Failure; List<StructDevice> listDevices() throws Error.Failure;
@ -497,13 +497,13 @@ public interface Signal extends DBusInterface {
class StructDevice extends Struct { class StructDevice extends Struct {
@Position(0) @Position(0)
DBusPath objectPath; final DBusPath objectPath;
@Position(1) @Position(1)
Long id; final Long id;
@Position(2) @Position(2)
String name; final String name;
public StructDevice(final DBusPath objectPath, final Long id, final String name) { public StructDevice(final DBusPath objectPath, final Long id, final String name) {
this.objectPath = objectPath; this.objectPath = objectPath;
@ -542,13 +542,13 @@ public interface Signal extends DBusInterface {
class StructGroup extends Struct { class StructGroup extends Struct {
@Position(0) @Position(0)
DBusPath objectPath; final DBusPath objectPath;
@Position(1) @Position(1)
byte[] id; final byte[] id;
@Position(2) @Position(2)
String name; final String name;
public StructGroup(final DBusPath objectPath, final byte[] id, final String name) { public StructGroup(final DBusPath objectPath, final byte[] id, final String name) {
this.objectPath = objectPath; this.objectPath = objectPath;
@ -610,13 +610,13 @@ public interface Signal extends DBusInterface {
class StructIdentity extends Struct { class StructIdentity extends Struct {
@Position(0) @Position(0)
DBusPath objectPath; final DBusPath objectPath;
@Position(1) @Position(1)
String uuid; final String uuid;
@Position(2) @Position(2)
String number; final String number;
public StructIdentity(final DBusPath objectPath, final String uuid, final String number) { public StructIdentity(final DBusPath objectPath, final String uuid, final String number) {
this.objectPath = objectPath; this.objectPath = objectPath;

View file

@ -165,20 +165,7 @@ public class App {
return; return;
} }
Set<String> accounts; account = getAccountIfOnlyOne(signalAccountFiles);
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();
} else if (!Manager.isValidNumber(account, null)) { } else if (!Manager.isValidNumber(account, null)) {
throw new UserErrorException("Invalid account (phone number), make sure you include the country code."); throw new UserErrorException("Invalid account (phone number), make sure you include the country code.");
} }
@ -196,6 +183,21 @@ public class App {
throw new UserErrorException("Command only works in multi-account mode"); throw new UserErrorException("Command only works in multi-account mode");
} }
private static String getAccountIfOnlyOne(final SignalAccountFiles signalAccountFiles) throws IOErrorException, UserErrorException {
Set<String> 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 { private OutputWriter getOutputWriter(final Command command) throws UserErrorException {
final var outputTypeInput = ns.<OutputType>get("output"); final var outputTypeInput = ns.<OutputType>get("output");
final var outputType = outputTypeInput == null ? command.getSupportedOutputTypes() final var outputType = outputTypeInput == null ? command.getSupportedOutputTypes()
@ -274,8 +276,6 @@ public class App {
) throws CommandException { ) throws CommandException {
try (var m = loadManager(account, signalAccountFiles)) { try (var m = loadManager(account, signalAccountFiles)) {
commandHandler.handleLocalCommand(command, m); commandHandler.handleLocalCommand(command, m);
} catch (IOException e) {
logger.warn("Cleanup failed", e);
} }
} }

View file

@ -10,8 +10,6 @@ import org.asamk.signal.manager.api.SendMessageResults;
import org.asamk.signal.output.OutputWriter; import org.asamk.signal.output.OutputWriter;
import org.asamk.signal.util.CommandUtil; import org.asamk.signal.util.CommandUtil;
import java.io.IOException;
import static org.asamk.signal.util.SendMessageResultUtils.outputResult; import static org.asamk.signal.util.SendMessageResultUtils.outputResult;
public class SendReceiptCommand implements JsonRpcLocalCommand { public class SendReceiptCommand implements JsonRpcLocalCommand {
@ -45,19 +43,14 @@ public class SendReceiptCommand implements JsonRpcLocalCommand {
final var targetTimestamps = ns.<Long>getList("target-timestamp"); final var targetTimestamps = ns.<Long>getList("target-timestamp");
final var type = ns.getString("type"); final var type = ns.getString("type");
try { final SendMessageResults results;
final SendMessageResults results; if (type == null || "read".equals(type)) {
if (type == null || "read".equals(type)) { results = m.sendReadReceipt(recipient, targetTimestamps);
results = m.sendReadReceipt(recipient, targetTimestamps); } else if ("viewed".equals(type)) {
} else if ("viewed".equals(type)) { results = m.sendViewedReceipt(recipient, targetTimestamps);
results = m.sendViewedReceipt(recipient, targetTimestamps); } else {
} else { throw new UserErrorException("Unknown receipt type: " + type);
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() + ")");
} }
outputResult(outputWriter, results);
} }
} }

View file

@ -4,14 +4,12 @@ import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser; import net.sourceforge.argparse4j.inf.Subparser;
import org.asamk.signal.commands.exceptions.CommandException; 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.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.api.Configuration; import org.asamk.signal.manager.api.Configuration;
import org.asamk.signal.manager.api.NotPrimaryDeviceException; import org.asamk.signal.manager.api.NotPrimaryDeviceException;
import org.asamk.signal.output.OutputWriter; import org.asamk.signal.output.OutputWriter;
import java.io.IOException;
import java.util.Optional; import java.util.Optional;
public class UpdateConfigurationCommand implements JsonRpcLocalCommand { public class UpdateConfigurationCommand implements JsonRpcLocalCommand {
@ -51,8 +49,6 @@ public class UpdateConfigurationCommand implements JsonRpcLocalCommand {
Optional.ofNullable(unidentifiedDeliveryIndicators), Optional.ofNullable(unidentifiedDeliveryIndicators),
Optional.ofNullable(typingIndicators), Optional.ofNullable(typingIndicators),
Optional.ofNullable(linkPreviews))); Optional.ofNullable(linkPreviews)));
} catch (IOException e) {
throw new IOErrorException("UpdateAccount error: " + e.getMessage(), e);
} catch (NotPrimaryDeviceException e) { } catch (NotPrimaryDeviceException e) {
throw new UserErrorException("This command doesn't work on linked devices."); throw new UserErrorException("This command doesn't work on linked devices.");
} }

View file

@ -136,7 +136,7 @@ public class DbusManagerImpl implements Manager {
} }
@Override @Override
public void updateConfiguration(Configuration newConfiguration) throws IOException { public void updateConfiguration(Configuration newConfiguration) {
final var configuration = getRemoteObject(new DBusPath(signal.getObjectPath() + "/Configuration"), final var configuration = getRemoteObject(new DBusPath(signal.getObjectPath() + "/Configuration"),
Signal.Configuration.class); Signal.Configuration.class);
newConfiguration.readReceipts() newConfiguration.readReceipts()

View file

@ -351,26 +351,16 @@ public class DbusSignalImpl implements Signal {
public void sendReadReceipt( public void sendReadReceipt(
final String recipient, final List<Long> messageIds final String recipient, final List<Long> messageIds
) throws Error.Failure, Error.UntrustedIdentity { ) throws Error.Failure, Error.UntrustedIdentity {
try { final var results = m.sendReadReceipt(getSingleRecipientIdentifier(recipient, m.getSelfNumber()), messageIds);
final var results = m.sendReadReceipt(getSingleRecipientIdentifier(recipient, m.getSelfNumber()), checkSendMessageResults(results);
messageIds);
checkSendMessageResults(results);
} catch (IOException e) {
throw new Error.Failure(e.getMessage());
}
} }
@Override @Override
public void sendViewedReceipt( public void sendViewedReceipt(
final String recipient, final List<Long> messageIds final String recipient, final List<Long> messageIds
) throws Error.Failure, Error.UntrustedIdentity { ) throws Error.Failure, Error.UntrustedIdentity {
try { final var results = m.sendViewedReceipt(getSingleRecipientIdentifier(recipient, m.getSelfNumber()), messageIds);
final var results = m.sendViewedReceipt(getSingleRecipientIdentifier(recipient, m.getSelfNumber()), checkSendMessageResults(results);
messageIds);
checkSendMessageResults(results);
} catch (IOException e) {
throw new Error.Failure(e.getMessage());
}
} }
@Override @Override
@ -532,8 +522,6 @@ public class DbusSignalImpl implements Signal {
m.setContactName(getSingleRecipientIdentifier(number, m.getSelfNumber()), name, ""); m.setContactName(getSingleRecipientIdentifier(number, m.getSelfNumber()), name, "");
} catch (NotPrimaryDeviceException e) { } catch (NotPrimaryDeviceException e) {
throw new Error.Failure("This command doesn't work on linked devices."); 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) { } catch (UnregisteredRecipientException e) {
throw new Error.UntrustedIdentity(e.getSender().getIdentifier() + " is not registered."); throw new Error.UntrustedIdentity(e.getSender().getIdentifier() + " is not registered.");
} }
@ -1238,8 +1226,6 @@ public class DbusSignalImpl implements Signal {
Optional.ofNullable(unidentifiedDeliveryIndicators), Optional.ofNullable(unidentifiedDeliveryIndicators),
Optional.ofNullable(typingIndicators), Optional.ofNullable(typingIndicators),
Optional.ofNullable(linkPreviews))); Optional.ofNullable(linkPreviews)));
} catch (IOException e) {
throw new Error.Failure("UpdateAccount error: " + e.getMessage());
} catch (NotPrimaryDeviceException e) { } catch (NotPrimaryDeviceException e) {
throw new Error.Failure("This command doesn't work on linked devices."); throw new Error.Failure("This command doesn't work on linked devices.");
} }