Commit 5c63cde4 authored by Finn Herzfeld's avatar Finn Herzfeld 🌵

Remove various unused methods

and one unused exception
parent 4b6c6b74
......@@ -17,14 +17,13 @@
package io.finn.signald;
import org.asamk.signal.storage.groups.GroupInfo;
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
import org.whispersystems.signalservice.internal.util.Base64;
import org.asamk.signal.storage.groups.GroupInfo;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.List;
class JsonGroupInfo {
String groupId;
......@@ -53,8 +52,8 @@ class JsonGroupInfo {
JsonGroupInfo(GroupInfo groupInfo, Manager m) {
this.groupId = Base64.encodeBytes(groupInfo.groupId);
this.name = groupInfo.name;
this.members = new ArrayList<String>(groupInfo.members);
this.avatarId = groupInfo.getAvatarId();
this.name = groupInfo.name;
this.members = new ArrayList<String>(groupInfo.members);
this.avatarId = groupInfo.getAvatarId();
}
}
......@@ -17,12 +17,7 @@
package io.finn.signald;
import java.util.Base64;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
import org.asamk.signal.storage.protocol.JsonIdentityKeyStore;
import io.finn.signald.storage.IdentityKeyStore;
import org.asamk.signal.util.Hex;
class JsonIdentity {
......@@ -32,13 +27,13 @@ class JsonIdentity {
public String safety_number;
public String username;
JsonIdentity(JsonIdentityKeyStore.Identity identity, Manager m) {
JsonIdentity(IdentityKeyStore.Identity identity, Manager m) {
this.trust_level = identity.getTrustLevel().name();
this.added = identity.getDateAdded().getTime();
this.fingerprint = Hex.toStringCondensed(identity.getFingerprint());
}
JsonIdentity(JsonIdentityKeyStore.Identity identity, Manager m, String username) {
JsonIdentity(IdentityKeyStore.Identity identity, Manager m, String username) {
this(identity, m);
this.safety_number = m.computeSafetyNumber(username, identity.getIdentityKey());
this.username = username;
......
......@@ -17,32 +17,32 @@
package io.finn.signald;
import java.util.List;
import io.finn.signald.storage.IdentityKeyStore;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.asamk.signal.storage.protocol.JsonIdentityKeyStore;
class JsonIdentityList {
public List<JsonIdentity> identities = new ArrayList<JsonIdentity>();
public List<JsonIdentity> identities = new ArrayList<>();
JsonIdentityList(List<JsonIdentityKeyStore.Identity> identities, Manager m) {
for(JsonIdentityKeyStore.Identity identity : identities) {
JsonIdentityList(List<IdentityKeyStore.Identity> identities, Manager m) {
for(IdentityKeyStore.Identity identity : identities) {
this.identities.add(new JsonIdentity(identity, m));
}
}
JsonIdentityList(String number, Manager m) {
if(number == null) {
for (Map.Entry<String, List<JsonIdentityKeyStore.Identity>> keys : m.getIdentities().entrySet()) {
for (JsonIdentityKeyStore.Identity identity : keys.getValue()) {
for (Map.Entry<String, List<IdentityKeyStore.Identity>> keys : m.getIdentities().entrySet()) {
for (IdentityKeyStore.Identity identity : keys.getValue()) {
this.identities.add(new JsonIdentity(identity, m, keys.getKey()));
}
}
} else {
List<JsonIdentityKeyStore.Identity> identities = m.getIdentities(number);
List<IdentityKeyStore.Identity> identities = m.getIdentities(number);
if(identities != null) {
for(JsonIdentityKeyStore.Identity identity : m.getIdentities(number)) {
for(IdentityKeyStore.Identity identity : m.getIdentities(number)) {
this.identities.add(new JsonIdentity(identity, m, number));
}
}
......
......@@ -20,7 +20,6 @@ package io.finn.signald;
import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
......
......@@ -17,17 +17,12 @@
package io.finn.signald;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.thoughtcrime.securesms.util.Hex;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import java.io.IOException;
class JsonSticker {
private static final Logger logger = LogManager.getLogger();
String packID;
String packKey;
int stickerID;
......
......@@ -23,11 +23,9 @@ import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSy
import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage;
import org.whispersystems.signalservice.internal.util.Base64;
import org.asamk.signal.util.Hex;
import java.io.IOException;
import java.util.List;
import java.util.LinkedList;
import java.util.List;
class JsonSyncMessage {
JsonSentTranscriptMessage sent;
......
......@@ -26,6 +26,7 @@ import java.nio.file.Files;
import java.security.Security;
import java.util.concurrent.ConcurrentHashMap;
import io.finn.signald.storage.AccountData;
import org.newsclub.net.unix.AFUNIXServerSocket;
import org.newsclub.net.unix.AFUNIXSocketAddress;
......@@ -99,6 +100,7 @@ public class Main implements Runnable {
logger.debug("Using data folder " + data_path);
Manager.setDataPath(data_path);
AccountData.setDataPath(data_path);
// Spins up one thread per registered signal number, listens for incoming messages
File[] users = new File(data_path + "/data").listFiles();
......
This diff is collapsed.
......@@ -17,22 +17,14 @@
package io.finn.signald;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ConcurrentHashMap;
import java.net.Socket;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.asamk.signal.AttachmentInvalidException;
import org.asamk.signal.GroupNotFoundException;
import org.asamk.signal.NotAGroupMemberException;
import org.asamk.signal.storage.contacts.ContactInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.TimeUnit;
class MessageReceiver implements Manager.ReceiveMessageHandler, Runnable {
final String username;
......@@ -69,15 +61,12 @@ class MessageReceiver implements Manager.ReceiveMessageHandler, Runnable {
while(sockets.size() > 0) {
double timeout = 3600;
boolean returnOnTimeout = true;
if (timeout < 0) {
returnOnTimeout = false;
timeout = 3600;
}
boolean ignoreAttachments = false;
try {
manager.receiveMessages((long) (timeout * 1000), TimeUnit.MILLISECONDS, returnOnTimeout, ignoreAttachments, this);
} catch (IOException e) {
logger.debug("probably harmless IOException while receiving messages:" + e.toString());
e.printStackTrace();
} catch (AssertionError e) {
logger.catching(e);
}
......
......@@ -17,53 +17,40 @@
package io.finn.signald;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.asamk.signal.*;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions;
import org.whispersystems.signalservice.internal.util.Base64;
import org.asamk.signal.storage.contacts.ContactInfo;
import org.asamk.signal.util.Hex;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.*;
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
import org.whispersystems.signalservice.api.messages.SendMessageResult;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions;
import org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
import org.asamk.signal.storage.contacts.ContactInfo;
import org.asamk.signal.util.Hex;
import org.whispersystems.signalservice.internal.util.Base64;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.*;
import java.net.Socket;
import java.net.URISyntaxException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeoutException;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.List;
import java.util.Locale;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonGenerator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeoutException;
public class SocketHandler implements Runnable {
private BufferedReader reader;
......@@ -215,7 +202,7 @@ public class SocketHandler implements Runnable {
}
}
private void send(JsonRequest request) throws IOException, EncapsulatedExceptions, UntrustedIdentityException, UntrustedIdentityException, GroupNotFoundException, GroupNotFoundException, AttachmentInvalidException, NotAGroupMemberException, NoSuchAccountException {
private void send(JsonRequest request) throws IOException, UntrustedIdentityException, GroupNotFoundException, AttachmentInvalidException, NotAGroupMemberException, NoSuchAccountException {
Manager manager = Manager.get(request.username);
SignalServiceDataMessage.Quote quote = null;
......@@ -227,7 +214,7 @@ public class SocketHandler implements Runnable {
if(request.attachmentFilenames != null) {
logger.warn("Using deprecated attachmentFilenames argument for send! Use attachments instead");
if(request.attachments == null) {
request.attachments = new ArrayList<JsonAttachment>();
request.attachments = new ArrayList<>();
}
for(String attachmentFilename: request.attachmentFilenames) {
request.attachments.add(new JsonAttachment(attachmentFilename));
......@@ -381,7 +368,7 @@ public class SocketHandler implements Runnable {
List<String> groupMembers = request.members;
if (groupMembers == null) {
groupMembers = new ArrayList<String>();
groupMembers = new ArrayList<>();
}
String groupAvatar = request.avatar;
......@@ -398,7 +385,7 @@ public class SocketHandler implements Runnable {
}
}
private void setExpiration(JsonRequest request) throws IOException, GroupNotFoundException, NotAGroupMemberException, AttachmentInvalidException, UntrustedIdentityException, EncapsulatedExceptions, IOException, NoSuchAccountException {
private void setExpiration(JsonRequest request) throws IOException, GroupNotFoundException, NotAGroupMemberException, AttachmentInvalidException, UntrustedIdentityException, EncapsulatedExceptions, NoSuchAccountException {
Manager m = Manager.get(request.username);
if(request.recipientGroupId != null) {
......@@ -411,12 +398,12 @@ public class SocketHandler implements Runnable {
this.reply("expiration_updated", null, request.id);
}
private void listGroups(JsonRequest request) throws IOException, JsonProcessingException, NoSuchAccountException {
private void listGroups(JsonRequest request) throws IOException, NoSuchAccountException {
Manager m = Manager.get(request.username);
this.reply("group_list", new JsonGroupList(m), request.id);
}
private void leaveGroup(JsonRequest request) throws IOException, JsonProcessingException, GroupNotFoundException, UntrustedIdentityException, NotAGroupMemberException, EncapsulatedExceptions, NoSuchAccountException {
private void leaveGroup(JsonRequest request) throws IOException, GroupNotFoundException, UntrustedIdentityException, NotAGroupMemberException, EncapsulatedExceptions, NoSuchAccountException {
Manager m = Manager.get(request.username);
byte[] groupId = Base64.decode(request.recipientGroupId);
m.sendQuitGroupMessage(groupId);
......@@ -445,8 +432,6 @@ public class SocketHandler implements Runnable {
this.reply("linking_successful", new JsonAccount(m), request.id);
} catch(TimeoutException e) {
this.reply("linking_error", new JsonStatusMessage(1, "Timed out while waiting for device to link", request), request.id);
} catch(IOException e) {
this.reply("linking_error", new JsonStatusMessage(2, e.getMessage(), request), request.id);
} catch(UserAlreadyExists e) {
this.reply("linking_error", new JsonStatusMessage(3, "The user " + e.getUsername() + " already exists. Delete \"" + e.getFileName() + "\" and trying again.", request), request.id);
}
......@@ -548,7 +533,7 @@ public class SocketHandler implements Runnable {
this.reply("subscribed", null, request.id); // TODO: Indicate if we actually subscribed or were already subscribed, also which username it was for
}
private void unsubscribe(JsonRequest request) throws IOException, NoSuchAccountException {
private void unsubscribe(JsonRequest request) throws IOException {
this.receivers.get(request.username).unsubscribe(this.socket);
this.receivers.remove(request.username);
this.subscribedAccounts.remove(request.username);
......
/*
* Copyright (C) 2019 Finn Herzfeld
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.finn.signald.exceptions;
import java.io.IOException;
public class InvalidStorageFileException extends IOException {
public InvalidStorageFileException(String message) {
super("Failed to load account data: " + message);
}
}
/*
* Copyright (C) 2020 Finn Herzfeld
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.finn.signald.storage;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import io.finn.signald.exceptions.InvalidStorageFileException;
import io.finn.signald.util.JSONHelper;
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
import org.whispersystems.signalservice.internal.util.Base64;
import java.io.File;
import java.io.IOException;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AccountData {
public String username;
public String password;
public int deviceId;
public String signalingKey;
public int preKeyIdOffset;
public int nextSignedPreKeyId;
public String profileKey;
public boolean registered;
public SignalProtocolStore axolotlStore;
public GroupStore groupStore;
public ContactStore contactStore;
public ThreadStore threadStore;
private static String dataPath;
public static AccountData load(File storageFile) throws IOException {
ObjectMapper mapper = JSONHelper.GetMapper();
// TODO: Add locking mechanism to prevent two instances of signald from using the same account at the same time.
AccountData a = mapper.readValue(storageFile, AccountData.class);
a.validate(); // Storage path passed for exceptions to include in messages
return a;
}
public void save() throws IOException {
save(false);
}
public void save(boolean allowBlankPassword) throws IOException {
validate();
ObjectWriter writer = JSONHelper.GetWriter();
File dataPathFile = new File(dataPath);
if(!dataPathFile.exists()) {
dataPathFile.mkdirs();
}
writer.writeValue(new File(dataPath + "/" + username), this);
}
public void validate() throws InvalidStorageFileException {
if (!PhoneNumberFormatter.isValidNumber(this.username, null)) {
throw new InvalidStorageFileException("phone number " + this.username + " is not valid");
}
}
public void init() {
if (groupStore == null) {
groupStore = new GroupStore();
}
if (contactStore == null) {
contactStore = new ContactStore();
}
if (threadStore == null) {
threadStore = new ThreadStore();
}
if (profileKey == null) {
profileKey = "";
}
}
public static void setDataPath(String path) {
dataPath = path + "/data";
}
public byte[] getProfileKey() throws IOException {
if(profileKey == null || profileKey.equals("")) {
return null;
}
return Base64.decode(profileKey);
}
public void setProfileKey(byte[] key) {
if(key == null) {
profileKey = "";
}
profileKey = Base64.encodeBytes(key);
}
}
/*
* Copyright (C) 2020 Finn Herzfeld
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.finn.signald.storage;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.asamk.signal.storage.contacts.ContactInfo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@JsonSerialize(using=ContactStore.ContactStoreSerializer.class)
@JsonDeserialize(using=ContactStore.ContactStoreDeserializer.class)
public class ContactStore {
private Map<String, ContactInfo> contacts = new HashMap<>();
private static final ObjectMapper jsonProcessor = new ObjectMapper();
public void updateContact(ContactInfo contact) {
contacts.put(contact.number, contact);
}
public ContactInfo getContact(String number) {
return contacts.get(number);
}
public List<ContactInfo> getContacts() {
return new ArrayList<>(contacts.values());
}
public void clear() {
contacts.clear();
}
public static class ContactStoreSerializer extends JsonSerializer<ContactStore> {
@Override
public void serialize(final ContactStore value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException {
jgen.writeStartObject();
jgen.writeObjectField("contacts", value.contacts.values());
jgen.writeEndObject();
}
}
public static class ContactStoreDeserializer extends JsonDeserializer<ContactStore> {
@Override
public ContactStore deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
ContactStore store = new ContactStore();
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
if(!node.has("contacts")) {
return store;
}
for (JsonNode n : node.get("contacts")) {
ContactInfo c = jsonProcessor.treeToValue(n, ContactInfo.class);
store.contacts.put(c.number, c);
}
return store;
}
}
}
/*
* Copyright (C) 2020 Finn Herzfeld
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package io.finn.signald.storage;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.asamk.signal.storage.groups.GroupInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.internal.util.Base64;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@JsonSerialize(using=GroupStore.GroupStoreSerializer.class)
@JsonDeserialize(using=GroupStore.GroupStoreDeserializer.class)
public class GroupStore {
static final Logger logger = LoggerFactory.getLogger(GroupStore.class);
private static final ObjectMapper jsonProcessor = new ObjectMapper();
private Map<String, GroupInfo> groups = new HashMap<>();
public static List<GroupInfo> groupsWithLegacyAvatarId = new ArrayList<>();
public void updateGroup(GroupInfo group) {
groups.put(Base64.encodeBytes(group.groupId), group);
}
public GroupInfo getGroup(byte[] groupId) {
return groups.get(Base64.encodeBytes(groupId));
}
public List<GroupInfo> getGroups() {
return new ArrayList<>(groups.values());
}
public static class GroupStoreSerializer extends JsonSerializer<GroupStore> {
@Override
public void serialize(final GroupStore value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException {
jgen.writeStartObject();
jgen.writeObjectField("groups", new ArrayList<>(value.groups.values()));
jgen.writeEndObject();
}
}
public static class GroupStoreDeserializer extends JsonDeserializer<GroupStore> {
@Override
public GroupStore deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
GroupStore store = new GroupStore();
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
if(!node.has("groups")) {
return store;
}
for (JsonNode n : node.get("groups")) {
logger.debug("Loading node %s", n.asText());
GroupInfo g = jsonProcessor.treeToValue(n, GroupInfo.class);
// Check if a legacy avatarId exists