mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 18:40:39 +00:00
Use slf4j simple logger
This commit is contained in:
parent
6a82029ab4
commit
5c754b6f5d
12 changed files with 237 additions and 183 deletions
|
@ -21,7 +21,7 @@ dependencies {
|
||||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.67'
|
implementation 'org.bouncycastle:bcprov-jdk15on:1.67'
|
||||||
implementation 'net.sourceforge.argparse4j:argparse4j:0.8.1'
|
implementation 'net.sourceforge.argparse4j:argparse4j:0.8.1'
|
||||||
implementation 'com.github.hypfvieh:dbus-java:3.2.4'
|
implementation 'com.github.hypfvieh:dbus-java:3.2.4'
|
||||||
implementation 'org.slf4j:slf4j-nop:1.7.30'
|
implementation 'org.slf4j:slf4j-simple:1.7.30'
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
|
|
|
@ -41,6 +41,8 @@ import org.asamk.signal.util.SecurityProvider;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
||||||
import org.freedesktop.dbus.exceptions.DBusException;
|
import org.freedesktop.dbus.exceptions.DBusException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
||||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
||||||
|
@ -50,10 +52,10 @@ import java.io.IOException;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.whispersystems.signalservice.internal.util.Util.isEmpty;
|
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
|
final static Logger logger = LoggerFactory.getLogger(Main.class);
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
installSecurityProviderWorkaround();
|
installSecurityProviderWorkaround();
|
||||||
|
|
||||||
|
@ -62,7 +64,7 @@ public class Main {
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = handleCommands(ns);
|
int res = init(ns);
|
||||||
System.exit(res);
|
System.exit(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,34 +74,18 @@ public class Main {
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int handleCommands(Namespace ns) {
|
public static int init(Namespace ns) {
|
||||||
|
if (ns.getBoolean("dbus") || ns.getBoolean("dbus_system")) {
|
||||||
|
return initDbusClient(ns, ns.getBoolean("dbus_system"));
|
||||||
|
}
|
||||||
|
|
||||||
final String username = ns.getString("username");
|
final String username = ns.getString("username");
|
||||||
|
|
||||||
if (ns.getBoolean("dbus") || ns.getBoolean("dbus_system")) {
|
final File dataPath;
|
||||||
try {
|
String config = ns.getString("config");
|
||||||
DBusConnection.DBusBusType busType;
|
if (config != null) {
|
||||||
if (ns.getBoolean("dbus_system")) {
|
dataPath = new File(config);
|
||||||
busType = DBusConnection.DBusBusType.SYSTEM;
|
|
||||||
} else {
|
} else {
|
||||||
busType = DBusConnection.DBusBusType.SESSION;
|
|
||||||
}
|
|
||||||
try (DBusConnection dBusConn = DBusConnection.getConnection(busType)) {
|
|
||||||
Signal ts = dBusConn.getRemoteObject(DbusConfig.SIGNAL_BUSNAME,
|
|
||||||
DbusConfig.SIGNAL_OBJECTPATH,
|
|
||||||
Signal.class);
|
|
||||||
|
|
||||||
return handleCommands(ns, ts, dBusConn);
|
|
||||||
}
|
|
||||||
} catch (UnsatisfiedLinkError e) {
|
|
||||||
System.err.println("Missing native library dependency for dbus service: " + e.getMessage());
|
|
||||||
return 1;
|
|
||||||
} catch (DBusException | IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String dataPath = ns.getString("config");
|
|
||||||
if (isEmpty(dataPath)) {
|
|
||||||
dataPath = getDefaultDataPath();
|
dataPath = getDefaultDataPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +93,7 @@ public class Main {
|
||||||
BaseConfig.USER_AGENT);
|
BaseConfig.USER_AGENT);
|
||||||
|
|
||||||
if (!ServiceConfig.getCapabilities().isGv2()) {
|
if (!ServiceConfig.getCapabilities().isGv2()) {
|
||||||
System.err.println("WARNING: Support for new group V2 is disabled,"
|
logger.warn("WARNING: Support for new group V2 is disabled,"
|
||||||
+ " because the required native library dependency is missing: libzkgroup");
|
+ " because the required native library dependency is missing: libzkgroup");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +106,7 @@ public class Main {
|
||||||
try {
|
try {
|
||||||
manager = Manager.init(username, dataPath, serviceConfiguration, BaseConfig.USER_AGENT);
|
manager = Manager.init(username, dataPath, serviceConfiguration, BaseConfig.USER_AGENT);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
System.err.println("Error loading state file: " + e.getMessage());
|
logger.error("Error loading state file: {}", e.getMessage());
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,16 +120,36 @@ public class Main {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Error while checking account: " + e.getMessage());
|
logger.error("Error while checking account: {}", e.getMessage());
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleCommands(ns, m);
|
return handleCommands(ns, m);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("Cleanup failed", e);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int initDbusClient(final Namespace ns, final boolean systemBus) {
|
||||||
|
try {
|
||||||
|
DBusConnection.DBusBusType busType;
|
||||||
|
if (systemBus) {
|
||||||
|
busType = DBusConnection.DBusBusType.SYSTEM;
|
||||||
|
} else {
|
||||||
|
busType = DBusConnection.DBusBusType.SESSION;
|
||||||
|
}
|
||||||
|
try (DBusConnection dBusConn = DBusConnection.getConnection(busType)) {
|
||||||
|
Signal ts = dBusConn.getRemoteObject(DbusConfig.SIGNAL_BUSNAME,
|
||||||
|
DbusConfig.SIGNAL_OBJECTPATH,
|
||||||
|
Signal.class);
|
||||||
|
|
||||||
|
return handleCommands(ns, ts, dBusConn);
|
||||||
|
}
|
||||||
|
} catch (DBusException | IOException e) {
|
||||||
|
logger.error("Dbus client failed", e);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int handleCommands(Namespace ns, Signal ts, DBusConnection dBusConn) {
|
private static int handleCommands(Namespace ns, Signal ts, DBusConnection dBusConn) {
|
||||||
|
@ -205,19 +211,19 @@ public class Main {
|
||||||
*
|
*
|
||||||
* @return the data directory to be used by signal-cli.
|
* @return the data directory to be used by signal-cli.
|
||||||
*/
|
*/
|
||||||
private static String getDefaultDataPath() {
|
private static File getDefaultDataPath() {
|
||||||
String dataPath = IOUtils.getDataHomeDir() + "/signal-cli";
|
File dataPath = new File(IOUtils.getDataHomeDir(), "/signal-cli");
|
||||||
if (new File(dataPath).exists()) {
|
if (dataPath.exists()) {
|
||||||
return dataPath;
|
return dataPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
String legacySettingsPath = System.getProperty("user.home") + "/.config/signal";
|
File legacySettingsPath = new File(System.getProperty("user.home"), "/.config/signal");
|
||||||
if (new File(legacySettingsPath).exists()) {
|
if (legacySettingsPath.exists()) {
|
||||||
return legacySettingsPath;
|
return legacySettingsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
legacySettingsPath = System.getProperty("user.home") + "/.config/textsecure";
|
legacySettingsPath = new File(System.getProperty("user.home"), "/.config/textsecure");
|
||||||
if (new File(legacySettingsPath).exists()) {
|
if (legacySettingsPath.exists()) {
|
||||||
return legacySettingsPath;
|
return legacySettingsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,32 +231,7 @@ public class Main {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Namespace parseArgs(String[] args) {
|
private static Namespace parseArgs(String[] args) {
|
||||||
ArgumentParser parser = ArgumentParsers.newFor("signal-cli")
|
ArgumentParser parser = buildArgumentParser();
|
||||||
.build()
|
|
||||||
.defaultHelp(true)
|
|
||||||
.description("Commandline interface for Signal.")
|
|
||||||
.version(BaseConfig.PROJECT_NAME + " " + BaseConfig.PROJECT_VERSION);
|
|
||||||
|
|
||||||
parser.addArgument("-v", "--version").help("Show package version.").action(Arguments.version());
|
|
||||||
parser.addArgument("--config")
|
|
||||||
.help("Set the path, where to store the config (Default: $XDG_DATA_HOME/signal-cli , $HOME/.local/share/signal-cli).");
|
|
||||||
|
|
||||||
MutuallyExclusiveGroup mut = parser.addMutuallyExclusiveGroup();
|
|
||||||
mut.addArgument("-u", "--username").help("Specify your phone number, that will be used for verification.");
|
|
||||||
mut.addArgument("--dbus").help("Make request via user dbus.").action(Arguments.storeTrue());
|
|
||||||
mut.addArgument("--dbus-system").help("Make request via system dbus.").action(Arguments.storeTrue());
|
|
||||||
|
|
||||||
Subparsers subparsers = parser.addSubparsers()
|
|
||||||
.title("subcommands")
|
|
||||||
.dest("command")
|
|
||||||
.description("valid subcommands")
|
|
||||||
.help("additional help");
|
|
||||||
|
|
||||||
final Map<String, Command> commands = Commands.getCommands();
|
|
||||||
for (Map.Entry<String, Command> entry : commands.entrySet()) {
|
|
||||||
Subparser subparser = subparsers.addParser(entry.getKey());
|
|
||||||
entry.getValue().attachToSubparser(subparser);
|
|
||||||
}
|
|
||||||
|
|
||||||
Namespace ns;
|
Namespace ns;
|
||||||
try {
|
try {
|
||||||
|
@ -283,4 +264,34 @@ public class Main {
|
||||||
}
|
}
|
||||||
return ns;
|
return ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ArgumentParser buildArgumentParser() {
|
||||||
|
ArgumentParser parser = ArgumentParsers.newFor("signal-cli")
|
||||||
|
.build()
|
||||||
|
.defaultHelp(true)
|
||||||
|
.description("Commandline interface for Signal.")
|
||||||
|
.version(BaseConfig.PROJECT_NAME + " " + BaseConfig.PROJECT_VERSION);
|
||||||
|
|
||||||
|
parser.addArgument("-v", "--version").help("Show package version.").action(Arguments.version());
|
||||||
|
parser.addArgument("--config")
|
||||||
|
.help("Set the path, where to store the config (Default: $XDG_DATA_HOME/signal-cli , $HOME/.local/share/signal-cli).");
|
||||||
|
|
||||||
|
MutuallyExclusiveGroup mut = parser.addMutuallyExclusiveGroup();
|
||||||
|
mut.addArgument("-u", "--username").help("Specify your phone number, that will be used for verification.");
|
||||||
|
mut.addArgument("--dbus").help("Make request via user dbus.").action(Arguments.storeTrue());
|
||||||
|
mut.addArgument("--dbus-system").help("Make request via system dbus.").action(Arguments.storeTrue());
|
||||||
|
|
||||||
|
Subparsers subparsers = parser.addSubparsers()
|
||||||
|
.title("subcommands")
|
||||||
|
.dest("command")
|
||||||
|
.description("valid subcommands")
|
||||||
|
.help("additional help");
|
||||||
|
|
||||||
|
final Map<String, Command> commands = Commands.getCommands();
|
||||||
|
for (Map.Entry<String, Command> entry : commands.entrySet()) {
|
||||||
|
Subparser subparser = subparsers.addParser(entry.getKey());
|
||||||
|
entry.getValue().attachToSubparser(subparser);
|
||||||
|
}
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,8 @@ import org.signal.zkgroup.groups.GroupSecretParams;
|
||||||
import org.signal.zkgroup.profiles.ClientZkProfileOperations;
|
import org.signal.zkgroup.profiles.ClientZkProfileOperations;
|
||||||
import org.signal.zkgroup.profiles.ProfileKey;
|
import org.signal.zkgroup.profiles.ProfileKey;
|
||||||
import org.signal.zkgroup.profiles.ProfileKeyCredential;
|
import org.signal.zkgroup.profiles.ProfileKeyCredential;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libsignal.IdentityKeyPair;
|
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||||
import org.whispersystems.libsignal.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
|
@ -173,6 +175,8 @@ import static org.asamk.signal.manager.ServiceConfig.getIasKeyStore;
|
||||||
|
|
||||||
public class Manager implements Closeable {
|
public class Manager implements Closeable {
|
||||||
|
|
||||||
|
final static Logger logger = LoggerFactory.getLogger(Manager.class);
|
||||||
|
|
||||||
private final SleepTimer timer = new UptimeSleepTimer();
|
private final SleepTimer timer = new UptimeSleepTimer();
|
||||||
|
|
||||||
private final SignalServiceConfiguration serviceConfiguration;
|
private final SignalServiceConfiguration serviceConfiguration;
|
||||||
|
@ -274,7 +278,7 @@ public class Manager implements Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Manager init(
|
public static Manager init(
|
||||||
String username, String settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent
|
String username, File settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
PathConfig pathConfig = PathConfig.createDefault(settingsPath);
|
PathConfig pathConfig = PathConfig.createDefault(settingsPath);
|
||||||
|
|
||||||
|
@ -590,7 +594,7 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
profile = retrieveRecipientProfile(address, profileKey);
|
profile = retrieveRecipientProfile(address, profileKey);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to retrieve profile, ignoring: " + e.getMessage());
|
logger.warn("Failed to retrieve profile, ignoring: {}", e.getMessage());
|
||||||
profileEntry.setRequestPending(false);
|
profileEntry.setRequestPending(false);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -613,7 +617,7 @@ public class Manager implements Closeable {
|
||||||
profileAndCredential = profileHelper.retrieveProfileSync(address,
|
profileAndCredential = profileHelper.retrieveProfileSync(address,
|
||||||
SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL);
|
SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to retrieve profile key credential, ignoring: " + e.getMessage());
|
logger.warn("Failed to retrieve profile key credential, ignoring: {}", e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,7 +650,7 @@ public class Manager implements Closeable {
|
||||||
? null
|
? null
|
||||||
: retrieveProfileAvatar(address, encryptedProfile.getAvatar(), profileKey);
|
: retrieveProfileAvatar(address, encryptedProfile.getAvatar(), profileKey);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
System.err.println("Failed to retrieve profile avatar, ignoring: " + e.getMessage());
|
logger.warn("Failed to retrieve profile avatar, ignoring: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileCipher profileCipher = new ProfileCipher(profileKey);
|
ProfileCipher profileCipher = new ProfileCipher(profileKey);
|
||||||
|
@ -1327,7 +1331,7 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
certificate = accountManager.getSenderCertificate();
|
certificate = accountManager.getSenderCertificate();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to get sender certificate: " + e);
|
logger.warn("Failed to get sender certificate, ignoring: {}", e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// TODO cache for a day
|
// TODO cache for a day
|
||||||
|
@ -1366,7 +1370,7 @@ public class Manager implements Closeable {
|
||||||
missingUuids.stream().map(a -> a.getNumber().get()).collect(Collectors.toSet()),
|
missingUuids.stream().map(a -> a.getNumber().get()).collect(Collectors.toSet()),
|
||||||
CDS_MRENCLAVE);
|
CDS_MRENCLAVE);
|
||||||
} catch (IOException | Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | SignatureException | UnauthenticatedResponseException e) {
|
} catch (IOException | Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | SignatureException | UnauthenticatedResponseException e) {
|
||||||
System.err.println("Failed to resolve uuids from server: " + e.getMessage());
|
logger.warn("Failed to resolve uuids from server, ignoring: {}", e.getMessage());
|
||||||
registeredUsers = new HashMap<>();
|
registeredUsers = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1570,8 +1574,9 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
retrieveGroupAvatarAttachment(avatar.asPointer(), groupV1.getGroupId());
|
retrieveGroupAvatarAttachment(avatar.asPointer(), groupV1.getGroupId());
|
||||||
} catch (IOException | InvalidMessageException | MissingConfigurationException e) {
|
} catch (IOException | InvalidMessageException | MissingConfigurationException e) {
|
||||||
System.err.println("Failed to retrieve group avatar (" + avatar.asPointer()
|
logger.warn("Failed to retrieve avatar for group {}, ignoring: {}",
|
||||||
.getRemoteId() + "): " + e.getMessage());
|
groupId.toBase64(),
|
||||||
|
e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1593,7 +1598,7 @@ public class Manager implements Closeable {
|
||||||
}
|
}
|
||||||
case DELIVER:
|
case DELIVER:
|
||||||
if (groupV1 == null && !isSync) {
|
if (groupV1 == null && !isSync) {
|
||||||
actions.add(new SendGroupInfoRequestAction(source, groupV1.getGroupId()));
|
actions.add(new SendGroupInfoRequestAction(source, groupId));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QUIT: {
|
case QUIT: {
|
||||||
|
@ -1658,10 +1663,9 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
retrieveAttachment(attachment.asPointer());
|
retrieveAttachment(attachment.asPointer());
|
||||||
} catch (IOException | InvalidMessageException | MissingConfigurationException e) {
|
} catch (IOException | InvalidMessageException | MissingConfigurationException e) {
|
||||||
System.err.println("Failed to retrieve attachment ("
|
logger.warn("Failed to retrieve attachment ({}), ignoring: {}",
|
||||||
+ attachment.asPointer().getRemoteId()
|
attachment.asPointer().getRemoteId(),
|
||||||
+ "): "
|
e.getMessage());
|
||||||
+ e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1686,10 +1690,9 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
retrieveAttachment(attachment);
|
retrieveAttachment(attachment);
|
||||||
} catch (IOException | InvalidMessageException | MissingConfigurationException e) {
|
} catch (IOException | InvalidMessageException | MissingConfigurationException e) {
|
||||||
System.err.println("Failed to retrieve attachment ("
|
logger.warn("Failed to retrieve preview image ({}), ignoring: {}",
|
||||||
+ attachment.getRemoteId()
|
attachment.getRemoteId(),
|
||||||
+ "): "
|
e.getMessage());
|
||||||
+ e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1703,10 +1706,9 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
retrieveAttachment(attachment.asPointer());
|
retrieveAttachment(attachment.asPointer());
|
||||||
} catch (IOException | InvalidMessageException | MissingConfigurationException e) {
|
} catch (IOException | InvalidMessageException | MissingConfigurationException e) {
|
||||||
System.err.println("Failed to retrieve attachment ("
|
logger.warn("Failed to retrieve quote attachment thumbnail ({}), ignoring: {}",
|
||||||
+ attachment.asPointer().getRemoteId()
|
attachment.asPointer().getRemoteId(),
|
||||||
+ "): "
|
e.getMessage());
|
||||||
+ e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1734,11 +1736,9 @@ public class Manager implements Closeable {
|
||||||
// Received a v2 group message for a v1 group, we need to locally migrate the group
|
// Received a v2 group message for a v1 group, we need to locally migrate the group
|
||||||
account.getGroupStore().deleteGroup(groupInfo.getGroupId());
|
account.getGroupStore().deleteGroup(groupInfo.getGroupId());
|
||||||
groupInfoV2 = new GroupInfoV2(groupId, groupMasterKey);
|
groupInfoV2 = new GroupInfoV2(groupId, groupMasterKey);
|
||||||
System.err.println("Locally migrated group "
|
logger.info("Locally migrated group {} to group v2, id: {}",
|
||||||
+ groupInfo.getGroupId().toBase64()
|
groupInfo.getGroupId().toBase64(),
|
||||||
+ " to group v2, id: "
|
groupInfoV2.getGroupId().toBase64());
|
||||||
+ groupInfoV2.getGroupId().toBase64()
|
|
||||||
+ " !!!");
|
|
||||||
} else if (groupInfo instanceof GroupInfoV2) {
|
} else if (groupInfo instanceof GroupInfoV2) {
|
||||||
groupInfoV2 = (GroupInfoV2) groupInfo;
|
groupInfoV2 = (GroupInfoV2) groupInfo;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1757,10 +1757,13 @@ public class Manager implements Closeable {
|
||||||
}
|
}
|
||||||
if (group != null) {
|
if (group != null) {
|
||||||
storeProfileKeysFromMembers(group);
|
storeProfileKeysFromMembers(group);
|
||||||
|
final String avatar = group.getAvatar();
|
||||||
|
if (avatar != null && !avatar.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
retrieveGroupAvatar(groupId, groupSecretParams, group.getAvatar());
|
retrieveGroupAvatar(groupId, groupSecretParams, avatar);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to download group avatar, ignoring ...");
|
logger.warn("Failed to download group avatar, ignoring: {}", e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
groupInfoV2.setGroup(group);
|
groupInfoV2.setGroup(group);
|
||||||
|
@ -1830,7 +1833,7 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
Files.delete(fileEntry.toPath());
|
Files.delete(fileEntry.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to delete cached message file “" + fileEntry + "”: " + e.getMessage());
|
logger.warn("Failed to delete cached message file “{}”, ignoring: {}", fileEntry, e.getMessage());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1848,7 +1851,7 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
Files.delete(fileEntry.toPath());
|
Files.delete(fileEntry.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to delete cached message file “" + fileEntry + "”: " + e.getMessage());
|
logger.warn("Failed to delete cached message file “{}”, ignoring: {}", fileEntry, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1880,8 +1883,7 @@ public class Manager implements Closeable {
|
||||||
File cacheFile = getMessageCacheFile(source, now, envelope1.getTimestamp());
|
File cacheFile = getMessageCacheFile(source, now, envelope1.getTimestamp());
|
||||||
Utils.storeEnvelope(envelope1, cacheFile);
|
Utils.storeEnvelope(envelope1, cacheFile);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to store encrypted message in disk cache, ignoring: "
|
logger.warn("Failed to store encrypted message in disk cache, ignoring: {}", e.getMessage());
|
||||||
+ e.getMessage());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (result.isPresent()) {
|
if (result.isPresent()) {
|
||||||
|
@ -1910,7 +1912,7 @@ public class Manager implements Closeable {
|
||||||
if (returnOnTimeout) return;
|
if (returnOnTimeout) return;
|
||||||
continue;
|
continue;
|
||||||
} catch (InvalidVersionException e) {
|
} catch (InvalidVersionException e) {
|
||||||
System.err.println("Ignoring error: " + e.getMessage());
|
logger.warn("Error while receiving messages, ignoring: {}", e.getMessage());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1954,7 +1956,7 @@ public class Manager implements Closeable {
|
||||||
// Try to delete directory if empty
|
// Try to delete directory if empty
|
||||||
new File(getMessageCachePath()).delete();
|
new File(getMessageCachePath()).delete();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to delete cached message file “" + cacheFile + "”: " + e.getMessage());
|
logger.warn("Failed to delete cached message file “{}”, ignoring: {}", cacheFile, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2088,16 +2090,18 @@ public class Manager implements Closeable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
logger.warn("Failed to handle received sync groups “{}”, ignoring: {}",
|
||||||
|
tmpFile,
|
||||||
|
e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
if (tmpFile != null) {
|
if (tmpFile != null) {
|
||||||
try {
|
try {
|
||||||
Files.delete(tmpFile.toPath());
|
Files.delete(tmpFile.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to delete received groups temp file “"
|
logger.warn("Failed to delete received groups temp file “{}”, ignoring: {}",
|
||||||
+ tmpFile
|
tmpFile,
|
||||||
+ "”: "
|
e.getMessage());
|
||||||
+ e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2114,8 +2118,8 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
setGroupBlocked(groupId, true);
|
setGroupBlocked(groupId, true);
|
||||||
} catch (GroupNotFoundException e) {
|
} catch (GroupNotFoundException e) {
|
||||||
System.err.println("BlockedListMessage contained groupID that was not found in GroupStore: "
|
logger.warn("BlockedListMessage contained groupID that was not found in GroupStore: {}",
|
||||||
+ groupId.toBase64());
|
groupId.toBase64());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2176,10 +2180,9 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
Files.delete(tmpFile.toPath());
|
Files.delete(tmpFile.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to delete received contacts temp file “"
|
logger.warn("Failed to delete received contacts temp file “{}”, ignoring: {}",
|
||||||
+ tmpFile
|
tmpFile,
|
||||||
+ "”: "
|
e.getMessage());
|
||||||
+ e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2275,7 +2278,9 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
Files.delete(tmpFile.toPath());
|
Files.delete(tmpFile.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to delete received avatar temp file “" + tmpFile + "”: " + e.getMessage());
|
logger.warn("Failed to delete received group avatar temp file “{}”, ignoring: {}",
|
||||||
|
tmpFile,
|
||||||
|
e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return outputFile;
|
return outputFile;
|
||||||
|
@ -2303,7 +2308,9 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
Files.delete(tmpFile.toPath());
|
Files.delete(tmpFile.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to delete received avatar temp file “" + tmpFile + "”: " + e.getMessage());
|
logger.warn("Failed to delete received profile avatar temp file “{}”, ignoring: {}",
|
||||||
|
tmpFile,
|
||||||
|
e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return outputFile;
|
return outputFile;
|
||||||
|
@ -2343,10 +2350,9 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
Files.delete(tmpFile.toPath());
|
Files.delete(tmpFile.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to delete received attachment temp file “"
|
logger.warn("Failed to delete received attachment temp file “{}”, ignoring: {}",
|
||||||
+ tmpFile
|
tmpFile,
|
||||||
+ "”: "
|
e.getMessage());
|
||||||
+ e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return outputFile;
|
return outputFile;
|
||||||
|
@ -2397,7 +2403,7 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
Files.delete(groupsFile.toPath());
|
Files.delete(groupsFile.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to delete groups temp file “" + groupsFile + "”: " + e.getMessage());
|
logger.warn("Failed to delete groups temp file “{}”, ignoring: {}", groupsFile, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2462,7 +2468,7 @@ public class Manager implements Closeable {
|
||||||
try {
|
try {
|
||||||
Files.delete(contactsFile.toPath());
|
Files.delete(contactsFile.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to delete contacts temp file “" + contactsFile + "”: " + e.getMessage());
|
logger.warn("Failed to delete contacts temp file “{}”, ignoring: {}", contactsFile, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,34 @@
|
||||||
package org.asamk.signal.manager;
|
package org.asamk.signal.manager;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
public class PathConfig {
|
public class PathConfig {
|
||||||
|
|
||||||
private final String dataPath;
|
private final File dataPath;
|
||||||
private final String attachmentsPath;
|
private final File attachmentsPath;
|
||||||
private final String avatarsPath;
|
private final File avatarsPath;
|
||||||
|
|
||||||
public static PathConfig createDefault(final String settingsPath) {
|
public static PathConfig createDefault(final File settingsPath) {
|
||||||
return new PathConfig(settingsPath + "/data", settingsPath + "/attachments", settingsPath + "/avatars");
|
return new PathConfig(new File(settingsPath, "/data"),
|
||||||
|
new File(settingsPath, "/attachments"),
|
||||||
|
new File(settingsPath, "/avatars"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PathConfig(final String dataPath, final String attachmentsPath, final String avatarsPath) {
|
private PathConfig(final File dataPath, final File attachmentsPath, final File avatarsPath) {
|
||||||
this.dataPath = dataPath;
|
this.dataPath = dataPath;
|
||||||
this.attachmentsPath = attachmentsPath;
|
this.attachmentsPath = attachmentsPath;
|
||||||
this.avatarsPath = avatarsPath;
|
this.avatarsPath = avatarsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDataPath() {
|
public String getDataPath() {
|
||||||
return dataPath;
|
return dataPath.getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAttachmentsPath() {
|
public String getAttachmentsPath() {
|
||||||
return attachmentsPath;
|
return attachmentsPath.getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAvatarsPath() {
|
public String getAvatarsPath() {
|
||||||
return avatarsPath;
|
return avatarsPath.getPath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
|
||||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
|
||||||
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
|
import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ public class ProvisioningManager {
|
||||||
private final int registrationId;
|
private final int registrationId;
|
||||||
private final String password;
|
private final String password;
|
||||||
|
|
||||||
public ProvisioningManager(String settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent) {
|
public ProvisioningManager(File settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent) {
|
||||||
this.pathConfig = PathConfig.createDefault(settingsPath);
|
this.pathConfig = PathConfig.createDefault(settingsPath);
|
||||||
this.serviceConfiguration = serviceConfiguration;
|
this.serviceConfiguration = serviceConfiguration;
|
||||||
this.userAgent = userAgent;
|
this.userAgent = userAgent;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.asamk.signal.manager.GroupIdV2;
|
||||||
import org.asamk.signal.manager.GroupLinkPassword;
|
import org.asamk.signal.manager.GroupLinkPassword;
|
||||||
import org.asamk.signal.manager.GroupUtils;
|
import org.asamk.signal.manager.GroupUtils;
|
||||||
import org.asamk.signal.storage.groups.GroupInfoV2;
|
import org.asamk.signal.storage.groups.GroupInfoV2;
|
||||||
|
import org.asamk.signal.storage.profiles.SignalProfile;
|
||||||
import org.asamk.signal.util.IOUtils;
|
import org.asamk.signal.util.IOUtils;
|
||||||
import org.signal.storageservice.protos.groups.AccessControl;
|
import org.signal.storageservice.protos.groups.AccessControl;
|
||||||
import org.signal.storageservice.protos.groups.GroupChange;
|
import org.signal.storageservice.protos.groups.GroupChange;
|
||||||
|
@ -20,6 +21,8 @@ import org.signal.zkgroup.groups.GroupMasterKey;
|
||||||
import org.signal.zkgroup.groups.GroupSecretParams;
|
import org.signal.zkgroup.groups.GroupSecretParams;
|
||||||
import org.signal.zkgroup.groups.UuidCiphertext;
|
import org.signal.zkgroup.groups.UuidCiphertext;
|
||||||
import org.signal.zkgroup.profiles.ProfileKeyCredential;
|
import org.signal.zkgroup.profiles.ProfileKeyCredential;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.util.Pair;
|
import org.whispersystems.libsignal.util.Pair;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||||
|
@ -44,6 +47,8 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class GroupHelper {
|
public class GroupHelper {
|
||||||
|
|
||||||
|
final static Logger logger = LoggerFactory.getLogger(GroupHelper.class);
|
||||||
|
|
||||||
private final ProfileKeyCredentialProvider profileKeyCredentialProvider;
|
private final ProfileKeyCredentialProvider profileKeyCredentialProvider;
|
||||||
|
|
||||||
private final ProfileProvider profileProvider;
|
private final ProfileProvider profileProvider;
|
||||||
|
@ -78,7 +83,7 @@ public class GroupHelper {
|
||||||
groupSecretParams);
|
groupSecretParams);
|
||||||
return groupsV2Api.getGroup(groupSecretParams, groupsV2AuthorizationString);
|
return groupsV2Api.getGroup(groupSecretParams, groupsV2AuthorizationString);
|
||||||
} catch (IOException | VerificationFailedException | InvalidGroupStateException e) {
|
} catch (IOException | VerificationFailedException | InvalidGroupStateException e) {
|
||||||
System.err.println("Failed to retrieve Group V2 info, ignoring ...");
|
logger.warn("Failed to retrieve Group V2 info, ignoring: {}", e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,11 +116,11 @@ public class GroupHelper {
|
||||||
groupsV2Api.putNewGroup(newGroup, groupAuthForToday);
|
groupsV2Api.putNewGroup(newGroup, groupAuthForToday);
|
||||||
decryptedGroup = groupsV2Api.getGroup(groupSecretParams, groupAuthForToday);
|
decryptedGroup = groupsV2Api.getGroup(groupSecretParams, groupAuthForToday);
|
||||||
} catch (IOException | VerificationFailedException | InvalidGroupStateException e) {
|
} catch (IOException | VerificationFailedException | InvalidGroupStateException e) {
|
||||||
System.err.println("Failed to create V2 group: " + e.getMessage());
|
logger.warn("Failed to create V2 group: {}", e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (decryptedGroup == null) {
|
if (decryptedGroup == null) {
|
||||||
System.err.println("Failed to create V2 group!");
|
logger.warn("Failed to create V2 group, unknown error!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +146,7 @@ public class GroupHelper {
|
||||||
final ProfileKeyCredential profileKeyCredential = profileKeyCredentialProvider.getProfileKeyCredential(
|
final ProfileKeyCredential profileKeyCredential = profileKeyCredentialProvider.getProfileKeyCredential(
|
||||||
selfAddressProvider.getSelfAddress());
|
selfAddressProvider.getSelfAddress());
|
||||||
if (profileKeyCredential == null) {
|
if (profileKeyCredential == null) {
|
||||||
System.err.println("Cannot create a V2 group as self does not have a versioned profile");
|
logger.warn("Cannot create a V2 group as self does not have a versioned profile");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,22 +170,23 @@ public class GroupHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean areMembersValid(final Collection<SignalServiceAddress> members) {
|
private boolean areMembersValid(final Collection<SignalServiceAddress> members) {
|
||||||
final int noUuidCapability = members.stream()
|
final Set<String> noUuidCapability = members.stream()
|
||||||
.filter(address -> !address.getUuid().isPresent())
|
.filter(address -> !address.getUuid().isPresent())
|
||||||
.collect(Collectors.toUnmodifiableSet())
|
.map(SignalServiceAddress::getLegacyIdentifier)
|
||||||
.size();
|
.collect(Collectors.toSet());
|
||||||
if (noUuidCapability > 0) {
|
if (noUuidCapability.size() > 0) {
|
||||||
System.err.println("Cannot create a V2 group as " + noUuidCapability + " members don't have a UUID.");
|
logger.warn("Cannot create a V2 group as some members don't have a UUID: {}",
|
||||||
|
String.join(", ", noUuidCapability));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int noGv2Capability = members.stream()
|
final Set<SignalProfile> noGv2Capability = members.stream()
|
||||||
.map(profileProvider::getProfile)
|
.map(profileProvider::getProfile)
|
||||||
.filter(profile -> profile != null && !profile.getCapabilities().gv2)
|
.filter(profile -> profile != null && !profile.getCapabilities().gv2)
|
||||||
.collect(Collectors.toUnmodifiableSet())
|
.collect(Collectors.toSet());
|
||||||
.size();
|
if (noGv2Capability.size() > 0) {
|
||||||
if (noGv2Capability > 0) {
|
logger.warn("Cannot create a V2 group as some members don't support Groups V2: {}",
|
||||||
System.err.println("Cannot create a V2 group as " + noGv2Capability + " members don't support Groups V2.");
|
noGv2Capability.stream().map(SignalProfile::getName).collect(Collectors.joining(", ")));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +225,9 @@ public class GroupHelper {
|
||||||
final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
|
final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
|
||||||
GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(groupSecretParams);
|
GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(groupSecretParams);
|
||||||
|
|
||||||
if (!areMembersValid(newMembers)) return null;
|
if (!areMembersValid(newMembers)) {
|
||||||
|
throw new IOException("Failed to update group");
|
||||||
|
}
|
||||||
|
|
||||||
Set<GroupCandidate> candidates = newMembers.stream()
|
Set<GroupCandidate> candidates = newMembers.stream()
|
||||||
.map(member -> new GroupCandidate(member.getUuid().get(),
|
.map(member -> new GroupCandidate(member.getUuid().get(),
|
||||||
|
|
|
@ -29,6 +29,8 @@ import org.asamk.signal.util.IOUtils;
|
||||||
import org.asamk.signal.util.Util;
|
import org.asamk.signal.util.Util;
|
||||||
import org.signal.zkgroup.InvalidInputException;
|
import org.signal.zkgroup.InvalidInputException;
|
||||||
import org.signal.zkgroup.profiles.ProfileKey;
|
import org.signal.zkgroup.profiles.ProfileKey;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.IdentityKeyPair;
|
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||||
import org.whispersystems.libsignal.state.PreKeyRecord;
|
import org.whispersystems.libsignal.state.PreKeyRecord;
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
|
@ -53,6 +55,8 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class SignalAccount implements Closeable {
|
public class SignalAccount implements Closeable {
|
||||||
|
|
||||||
|
final static Logger logger = LoggerFactory.getLogger(SignalAccount.class);
|
||||||
|
|
||||||
private final ObjectMapper jsonProcessor = new ObjectMapper();
|
private final ObjectMapper jsonProcessor = new ObjectMapper();
|
||||||
private final FileChannel fileChannel;
|
private final FileChannel fileChannel;
|
||||||
private final FileLock lock;
|
private final FileLock lock;
|
||||||
|
@ -357,7 +361,7 @@ public class SignalAccount implements Closeable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println(String.format("Error saving file: %s", e.getMessage()));
|
logger.error("Error saving file: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,9 +369,9 @@ public class SignalAccount implements Closeable {
|
||||||
FileChannel fileChannel = new RandomAccessFile(new File(fileName), "rw").getChannel();
|
FileChannel fileChannel = new RandomAccessFile(new File(fileName), "rw").getChannel();
|
||||||
FileLock lock = fileChannel.tryLock();
|
FileLock lock = fileChannel.tryLock();
|
||||||
if (lock == null) {
|
if (lock == null) {
|
||||||
System.err.println("Config file is in use by another instance, waiting…");
|
logger.info("Config file is in use by another instance, waiting…");
|
||||||
lock = fileChannel.lock();
|
lock = fileChannel.lock();
|
||||||
System.err.println("Config file lock acquired.");
|
logger.info("Config file lock acquired.");
|
||||||
}
|
}
|
||||||
return new Pair<>(fileChannel, lock);
|
return new Pair<>(fileChannel, lock);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ import org.asamk.signal.util.IOUtils;
|
||||||
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
import org.signal.storageservice.protos.groups.local.DecryptedGroup;
|
||||||
import org.signal.zkgroup.InvalidInputException;
|
import org.signal.zkgroup.InvalidInputException;
|
||||||
import org.signal.zkgroup.groups.GroupMasterKey;
|
import org.signal.zkgroup.groups.GroupMasterKey;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.util.Base64;
|
import org.whispersystems.util.Base64;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -35,6 +37,8 @@ import java.util.Map;
|
||||||
|
|
||||||
public class JsonGroupStore {
|
public class JsonGroupStore {
|
||||||
|
|
||||||
|
final static Logger logger = LoggerFactory.getLogger(JsonGroupStore.class);
|
||||||
|
|
||||||
private static final ObjectMapper jsonProcessor = new ObjectMapper();
|
private static final ObjectMapper jsonProcessor = new ObjectMapper();
|
||||||
public File groupCachePath;
|
public File groupCachePath;
|
||||||
|
|
||||||
|
@ -63,7 +67,7 @@ public class JsonGroupStore {
|
||||||
groupFileLegacy.delete();
|
groupFileLegacy.delete();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to cache group, ignoring ...");
|
logger.warn("Failed to cache group, ignoring: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
|
||||||
import org.asamk.signal.manager.TrustLevel;
|
import org.asamk.signal.manager.TrustLevel;
|
||||||
import org.asamk.signal.util.Util;
|
import org.asamk.signal.util.Util;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.libsignal.IdentityKeyPair;
|
import org.whispersystems.libsignal.IdentityKeyPair;
|
||||||
import org.whispersystems.libsignal.InvalidKeyException;
|
import org.whispersystems.libsignal.InvalidKeyException;
|
||||||
|
@ -27,6 +29,8 @@ import java.util.UUID;
|
||||||
|
|
||||||
public class JsonIdentityKeyStore implements IdentityKeyStore {
|
public class JsonIdentityKeyStore implements IdentityKeyStore {
|
||||||
|
|
||||||
|
final static Logger logger = LoggerFactory.getLogger(JsonIdentityKeyStore.class);
|
||||||
|
|
||||||
private final List<Identity> identities = new ArrayList<>();
|
private final List<Identity> identities = new ArrayList<>();
|
||||||
|
|
||||||
private final IdentityKeyPair identityKeyPair;
|
private final IdentityKeyPair identityKeyPair;
|
||||||
|
@ -219,7 +223,7 @@ public class JsonIdentityKeyStore implements IdentityKeyStore {
|
||||||
.asLong()) : new Date();
|
.asLong()) : new Date();
|
||||||
keyStore.saveIdentity(serviceAddress, id, trustLevel, added);
|
keyStore.saveIdentity(serviceAddress, id, trustLevel, added);
|
||||||
} catch (InvalidKeyException | IOException e) {
|
} catch (InvalidKeyException | IOException e) {
|
||||||
System.out.println(String.format("Error while decoding key for: %s", trustedKeyName));
|
logger.warn("Error while decoding key for {}: {}", trustedKeyName, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.InvalidKeyIdException;
|
import org.whispersystems.libsignal.InvalidKeyIdException;
|
||||||
import org.whispersystems.libsignal.state.PreKeyRecord;
|
import org.whispersystems.libsignal.state.PreKeyRecord;
|
||||||
import org.whispersystems.libsignal.state.PreKeyStore;
|
import org.whispersystems.libsignal.state.PreKeyStore;
|
||||||
|
@ -19,6 +21,8 @@ import java.util.Map;
|
||||||
|
|
||||||
class JsonPreKeyStore implements PreKeyStore {
|
class JsonPreKeyStore implements PreKeyStore {
|
||||||
|
|
||||||
|
final static Logger logger = LoggerFactory.getLogger(JsonPreKeyStore.class);
|
||||||
|
|
||||||
private final Map<Integer, byte[]> store = new HashMap<>();
|
private final Map<Integer, byte[]> store = new HashMap<>();
|
||||||
|
|
||||||
public JsonPreKeyStore() {
|
public JsonPreKeyStore() {
|
||||||
|
@ -72,7 +76,7 @@ class JsonPreKeyStore implements PreKeyStore {
|
||||||
try {
|
try {
|
||||||
preKeyMap.put(preKeyId, Base64.decode(preKey.get("record").asText()));
|
preKeyMap.put(preKeyId, Base64.decode(preKey.get("record").asText()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println(String.format("Error while decoding prekey for: %s", preKeyId));
|
logger.warn("Error while decoding prekey for {}: {}", preKeyId, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
|
||||||
import org.asamk.signal.util.Util;
|
import org.asamk.signal.util.Util;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||||
import org.whispersystems.libsignal.state.SessionRecord;
|
import org.whispersystems.libsignal.state.SessionRecord;
|
||||||
import org.whispersystems.libsignal.state.SessionStore;
|
import org.whispersystems.libsignal.state.SessionStore;
|
||||||
|
@ -24,6 +26,8 @@ import java.util.UUID;
|
||||||
|
|
||||||
class JsonSessionStore implements SessionStore {
|
class JsonSessionStore implements SessionStore {
|
||||||
|
|
||||||
|
final static Logger logger = LoggerFactory.getLogger(JsonSessionStore.class);
|
||||||
|
|
||||||
private final List<SessionInfo> sessions = new ArrayList<>();
|
private final List<SessionInfo> sessions = new ArrayList<>();
|
||||||
|
|
||||||
private SignalServiceAddressResolver resolver;
|
private SignalServiceAddressResolver resolver;
|
||||||
|
@ -51,7 +55,7 @@ class JsonSessionStore implements SessionStore {
|
||||||
try {
|
try {
|
||||||
return new SessionRecord(info.sessionRecord);
|
return new SessionRecord(info.sessionRecord);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Failed to load session, resetting session: " + e);
|
logger.warn("Failed to load session, resetting session: {}", e.getMessage());
|
||||||
final SessionRecord sessionRecord = new SessionRecord();
|
final SessionRecord sessionRecord = new SessionRecord();
|
||||||
info.sessionRecord = sessionRecord.serialize();
|
info.sessionRecord = sessionRecord.serialize();
|
||||||
return sessionRecord;
|
return sessionRecord;
|
||||||
|
@ -151,7 +155,7 @@ class JsonSessionStore implements SessionStore {
|
||||||
SessionInfo sessionInfo = new SessionInfo(serviceAddress, deviceId, Base64.decode(record));
|
SessionInfo sessionInfo = new SessionInfo(serviceAddress, deviceId, Base64.decode(record));
|
||||||
sessionStore.sessions.add(sessionInfo);
|
sessionStore.sessions.add(sessionInfo);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println(String.format("Error while decoding session for: %s", sessionName));
|
logger.warn("Error while decoding session for {}: {}", sessionName, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.whispersystems.libsignal.InvalidKeyIdException;
|
import org.whispersystems.libsignal.InvalidKeyIdException;
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||||
import org.whispersystems.libsignal.state.SignedPreKeyStore;
|
import org.whispersystems.libsignal.state.SignedPreKeyStore;
|
||||||
|
@ -21,6 +23,8 @@ import java.util.Map;
|
||||||
|
|
||||||
class JsonSignedPreKeyStore implements SignedPreKeyStore {
|
class JsonSignedPreKeyStore implements SignedPreKeyStore {
|
||||||
|
|
||||||
|
final static Logger logger = LoggerFactory.getLogger(JsonSignedPreKeyStore.class);
|
||||||
|
|
||||||
private final Map<Integer, byte[]> store = new HashMap<>();
|
private final Map<Integer, byte[]> store = new HashMap<>();
|
||||||
|
|
||||||
public JsonSignedPreKeyStore() {
|
public JsonSignedPreKeyStore() {
|
||||||
|
@ -89,7 +93,7 @@ class JsonSignedPreKeyStore implements SignedPreKeyStore {
|
||||||
try {
|
try {
|
||||||
preKeyMap.put(preKeyId, Base64.decode(preKey.get("record").asText()));
|
preKeyMap.put(preKeyId, Base64.decode(preKey.get("record").asText()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println(String.format("Error while decoding prekey for: %s", preKeyId));
|
logger.warn("Error while decoding prekey for {}: {}", preKeyId, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue