From: AsamK Date: Fri, 25 Dec 2020 21:34:30 +0000 (+0100) Subject: Use slf4j simple logger X-Git-Tag: v0.7.2~8 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/5c754b6f5d5bd3273b3c0722cf3eabbcd02c20b9?ds=sidebyside Use slf4j simple logger --- diff --git a/build.gradle b/build.gradle index 48b57a4f..1fbf5948 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ dependencies { implementation 'org.bouncycastle:bcprov-jdk15on:1.67' implementation 'net.sourceforge.argparse4j:argparse4j:0.8.1' 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 { diff --git a/src/main/java/org/asamk/signal/Main.java b/src/main/java/org/asamk/signal/Main.java index de827b1c..97e3f9b2 100644 --- a/src/main/java/org/asamk/signal/Main.java +++ b/src/main/java/org/asamk/signal/Main.java @@ -41,6 +41,8 @@ import org.asamk.signal.util.SecurityProvider; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.freedesktop.dbus.connections.impl.DBusConnection; 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.util.PhoneNumberFormatter; import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration; @@ -50,10 +52,10 @@ import java.io.IOException; import java.security.Security; import java.util.Map; -import static org.whispersystems.signalservice.internal.util.Util.isEmpty; - public class Main { + final static Logger logger = LoggerFactory.getLogger(Main.class); + public static void main(String[] args) { installSecurityProviderWorkaround(); @@ -62,7 +64,7 @@ public class Main { System.exit(1); } - int res = handleCommands(ns); + int res = init(ns); System.exit(res); } @@ -72,77 +74,81 @@ public class Main { Security.addProvider(new BouncyCastleProvider()); } - private static int handleCommands(Namespace ns) { - final String username = ns.getString("username"); - + public static int init(Namespace ns) { if (ns.getBoolean("dbus") || ns.getBoolean("dbus_system")) { - try { - DBusConnection.DBusBusType busType; - if (ns.getBoolean("dbus_system")) { - 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 initDbusClient(ns, ns.getBoolean("dbus_system")); + } - 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; - } + final String username = ns.getString("username"); + + final File dataPath; + String config = ns.getString("config"); + if (config != null) { + dataPath = new File(config); } else { - String dataPath = ns.getString("config"); - if (isEmpty(dataPath)) { - dataPath = getDefaultDataPath(); - } + dataPath = getDefaultDataPath(); + } - final SignalServiceConfiguration serviceConfiguration = ServiceConfig.createDefaultServiceConfiguration( - BaseConfig.USER_AGENT); + final SignalServiceConfiguration serviceConfiguration = ServiceConfig.createDefaultServiceConfiguration( + BaseConfig.USER_AGENT); - if (!ServiceConfig.getCapabilities().isGv2()) { - System.err.println("WARNING: Support for new group V2 is disabled," - + " because the required native library dependency is missing: libzkgroup"); - } + if (!ServiceConfig.getCapabilities().isGv2()) { + logger.warn("WARNING: Support for new group V2 is disabled," + + " because the required native library dependency is missing: libzkgroup"); + } - if (username == null) { - ProvisioningManager pm = new ProvisioningManager(dataPath, serviceConfiguration, BaseConfig.USER_AGENT); - return handleCommands(ns, pm); - } + if (username == null) { + ProvisioningManager pm = new ProvisioningManager(dataPath, serviceConfiguration, BaseConfig.USER_AGENT); + return handleCommands(ns, pm); + } - Manager manager; + Manager manager; + try { + manager = Manager.init(username, dataPath, serviceConfiguration, BaseConfig.USER_AGENT); + } catch (Throwable e) { + logger.error("Error loading state file: {}", e.getMessage()); + return 2; + } + + try (Manager m = manager) { try { - manager = Manager.init(username, dataPath, serviceConfiguration, BaseConfig.USER_AGENT); - } catch (Throwable e) { - System.err.println("Error loading state file: " + e.getMessage()); + m.checkAccountState(); + } catch (AuthorizationFailedException e) { + if (!"register".equals(ns.getString("command"))) { + // Register command should still be possible, if current authorization fails + System.err.println("Authorization failed, was the number registered elsewhere?"); + return 2; + } + } catch (IOException e) { + logger.error("Error while checking account: {}", e.getMessage()); return 2; } - try (Manager m = manager) { - try { - m.checkAccountState(); - } catch (AuthorizationFailedException e) { - if (!"register".equals(ns.getString("command"))) { - // Register command should still be possible, if current authorization fails - System.err.println("Authorization failed, was the number registered elsewhere?"); - return 2; - } - } catch (IOException e) { - System.err.println("Error while checking account: " + e.getMessage()); - return 2; - } + return handleCommands(ns, m); + } catch (IOException e) { + logger.error("Cleanup failed", e); + return 3; + } + } - return handleCommands(ns, m); - } catch (IOException e) { - e.printStackTrace(); - 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; } } @@ -205,19 +211,19 @@ public class Main { * * @return the data directory to be used by signal-cli. */ - private static String getDefaultDataPath() { - String dataPath = IOUtils.getDataHomeDir() + "/signal-cli"; - if (new File(dataPath).exists()) { + private static File getDefaultDataPath() { + File dataPath = new File(IOUtils.getDataHomeDir(), "/signal-cli"); + if (dataPath.exists()) { return dataPath; } - String legacySettingsPath = System.getProperty("user.home") + "/.config/signal"; - if (new File(legacySettingsPath).exists()) { + File legacySettingsPath = new File(System.getProperty("user.home"), "/.config/signal"); + if (legacySettingsPath.exists()) { return legacySettingsPath; } - legacySettingsPath = System.getProperty("user.home") + "/.config/textsecure"; - if (new File(legacySettingsPath).exists()) { + legacySettingsPath = new File(System.getProperty("user.home"), "/.config/textsecure"); + if (legacySettingsPath.exists()) { return legacySettingsPath; } @@ -225,32 +231,7 @@ public class Main { } private static Namespace parseArgs(String[] args) { - 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 commands = Commands.getCommands(); - for (Map.Entry entry : commands.entrySet()) { - Subparser subparser = subparsers.addParser(entry.getKey()); - entry.getValue().attachToSubparser(subparser); - } + ArgumentParser parser = buildArgumentParser(); Namespace ns; try { @@ -283,4 +264,34 @@ public class Main { } 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 commands = Commands.getCommands(); + for (Map.Entry entry : commands.entrySet()) { + Subparser subparser = subparsers.addParser(entry.getKey()); + entry.getValue().attachToSubparser(subparser); + } + return parser; + } } diff --git a/src/main/java/org/asamk/signal/manager/Manager.java b/src/main/java/org/asamk/signal/manager/Manager.java index 2553a416..c679449d 100644 --- a/src/main/java/org/asamk/signal/manager/Manager.java +++ b/src/main/java/org/asamk/signal/manager/Manager.java @@ -55,6 +55,8 @@ import org.signal.zkgroup.groups.GroupSecretParams; import org.signal.zkgroup.profiles.ClientZkProfileOperations; import org.signal.zkgroup.profiles.ProfileKey; import org.signal.zkgroup.profiles.ProfileKeyCredential; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.InvalidKeyException; @@ -173,6 +175,8 @@ import static org.asamk.signal.manager.ServiceConfig.getIasKeyStore; public class Manager implements Closeable { + final static Logger logger = LoggerFactory.getLogger(Manager.class); + private final SleepTimer timer = new UptimeSleepTimer(); private final SignalServiceConfiguration serviceConfiguration; @@ -274,7 +278,7 @@ public class Manager implements Closeable { } public static Manager init( - String username, String settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent + String username, File settingsPath, SignalServiceConfiguration serviceConfiguration, String userAgent ) throws IOException { PathConfig pathConfig = PathConfig.createDefault(settingsPath); @@ -590,7 +594,7 @@ public class Manager implements Closeable { try { profile = retrieveRecipientProfile(address, profileKey); } 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); return null; } @@ -613,7 +617,7 @@ public class Manager implements Closeable { profileAndCredential = profileHelper.retrieveProfileSync(address, SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL); } 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; } @@ -646,7 +650,7 @@ public class Manager implements Closeable { ? null : retrieveProfileAvatar(address, encryptedProfile.getAvatar(), profileKey); } 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); @@ -1327,7 +1331,7 @@ public class Manager implements Closeable { try { certificate = accountManager.getSenderCertificate(); } catch (IOException e) { - System.err.println("Failed to get sender certificate: " + e); + logger.warn("Failed to get sender certificate, ignoring: {}", e.getMessage()); return null; } // TODO cache for a day @@ -1366,7 +1370,7 @@ public class Manager implements Closeable { missingUuids.stream().map(a -> a.getNumber().get()).collect(Collectors.toSet()), CDS_MRENCLAVE); } 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<>(); } @@ -1570,8 +1574,9 @@ public class Manager implements Closeable { try { retrieveGroupAvatarAttachment(avatar.asPointer(), groupV1.getGroupId()); } catch (IOException | InvalidMessageException | MissingConfigurationException e) { - System.err.println("Failed to retrieve group avatar (" + avatar.asPointer() - .getRemoteId() + "): " + e.getMessage()); + logger.warn("Failed to retrieve avatar for group {}, ignoring: {}", + groupId.toBase64(), + e.getMessage()); } } } @@ -1593,7 +1598,7 @@ public class Manager implements Closeable { } case DELIVER: if (groupV1 == null && !isSync) { - actions.add(new SendGroupInfoRequestAction(source, groupV1.getGroupId())); + actions.add(new SendGroupInfoRequestAction(source, groupId)); } break; case QUIT: { @@ -1658,10 +1663,9 @@ public class Manager implements Closeable { try { retrieveAttachment(attachment.asPointer()); } catch (IOException | InvalidMessageException | MissingConfigurationException e) { - System.err.println("Failed to retrieve attachment (" - + attachment.asPointer().getRemoteId() - + "): " - + e.getMessage()); + logger.warn("Failed to retrieve attachment ({}), ignoring: {}", + attachment.asPointer().getRemoteId(), + e.getMessage()); } } } @@ -1686,10 +1690,9 @@ public class Manager implements Closeable { try { retrieveAttachment(attachment); } catch (IOException | InvalidMessageException | MissingConfigurationException e) { - System.err.println("Failed to retrieve attachment (" - + attachment.getRemoteId() - + "): " - + e.getMessage()); + logger.warn("Failed to retrieve preview image ({}), ignoring: {}", + attachment.getRemoteId(), + e.getMessage()); } } } @@ -1703,10 +1706,9 @@ public class Manager implements Closeable { try { retrieveAttachment(attachment.asPointer()); } catch (IOException | InvalidMessageException | MissingConfigurationException e) { - System.err.println("Failed to retrieve attachment (" - + attachment.asPointer().getRemoteId() - + "): " - + e.getMessage()); + logger.warn("Failed to retrieve quote attachment thumbnail ({}), ignoring: {}", + attachment.asPointer().getRemoteId(), + 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 account.getGroupStore().deleteGroup(groupInfo.getGroupId()); groupInfoV2 = new GroupInfoV2(groupId, groupMasterKey); - System.err.println("Locally migrated group " - + groupInfo.getGroupId().toBase64() - + " to group v2, id: " - + groupInfoV2.getGroupId().toBase64() - + " !!!"); + logger.info("Locally migrated group {} to group v2, id: {}", + groupInfo.getGroupId().toBase64(), + groupInfoV2.getGroupId().toBase64()); } else if (groupInfo instanceof GroupInfoV2) { groupInfoV2 = (GroupInfoV2) groupInfo; } else { @@ -1757,10 +1757,13 @@ public class Manager implements Closeable { } if (group != null) { storeProfileKeysFromMembers(group); - try { - retrieveGroupAvatar(groupId, groupSecretParams, group.getAvatar()); - } catch (IOException e) { - System.err.println("Failed to download group avatar, ignoring ..."); + final String avatar = group.getAvatar(); + if (avatar != null && !avatar.isEmpty()) { + try { + retrieveGroupAvatar(groupId, groupSecretParams, avatar); + } catch (IOException e) { + logger.warn("Failed to download group avatar, ignoring: {}", e.getMessage()); + } } } groupInfoV2.setGroup(group); @@ -1830,7 +1833,7 @@ public class Manager implements Closeable { try { Files.delete(fileEntry.toPath()); } 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; } @@ -1848,7 +1851,7 @@ public class Manager implements Closeable { try { Files.delete(fileEntry.toPath()); } 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()); Utils.storeEnvelope(envelope1, cacheFile); } catch (IOException e) { - System.err.println("Failed to store encrypted message in disk cache, ignoring: " - + e.getMessage()); + logger.warn("Failed to store encrypted message in disk cache, ignoring: {}", e.getMessage()); } }); if (result.isPresent()) { @@ -1910,7 +1912,7 @@ public class Manager implements Closeable { if (returnOnTimeout) return; continue; } catch (InvalidVersionException e) { - System.err.println("Ignoring error: " + e.getMessage()); + logger.warn("Error while receiving messages, ignoring: {}", e.getMessage()); continue; } @@ -1954,7 +1956,7 @@ public class Manager implements Closeable { // Try to delete directory if empty new File(getMessageCachePath()).delete(); } 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) { + logger.warn("Failed to handle received sync groups “{}”, ignoring: {}", + tmpFile, + e.getMessage()); e.printStackTrace(); } finally { if (tmpFile != null) { try { Files.delete(tmpFile.toPath()); } catch (IOException e) { - System.err.println("Failed to delete received groups temp file “" - + tmpFile - + "”: " - + e.getMessage()); + logger.warn("Failed to delete received groups temp file “{}”, ignoring: {}", + tmpFile, + e.getMessage()); } } } @@ -2114,8 +2118,8 @@ public class Manager implements Closeable { try { setGroupBlocked(groupId, true); } catch (GroupNotFoundException e) { - System.err.println("BlockedListMessage contained groupID that was not found in GroupStore: " - + groupId.toBase64()); + logger.warn("BlockedListMessage contained groupID that was not found in GroupStore: {}", + groupId.toBase64()); } } } @@ -2176,10 +2180,9 @@ public class Manager implements Closeable { try { Files.delete(tmpFile.toPath()); } catch (IOException e) { - System.err.println("Failed to delete received contacts temp file “" - + tmpFile - + "”: " - + e.getMessage()); + logger.warn("Failed to delete received contacts temp file “{}”, ignoring: {}", + tmpFile, + e.getMessage()); } } } @@ -2275,7 +2278,9 @@ public class Manager implements Closeable { try { Files.delete(tmpFile.toPath()); } 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; @@ -2303,7 +2308,9 @@ public class Manager implements Closeable { try { Files.delete(tmpFile.toPath()); } 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; @@ -2343,10 +2350,9 @@ public class Manager implements Closeable { try { Files.delete(tmpFile.toPath()); } catch (IOException e) { - System.err.println("Failed to delete received attachment temp file “" - + tmpFile - + "”: " - + e.getMessage()); + logger.warn("Failed to delete received attachment temp file “{}”, ignoring: {}", + tmpFile, + e.getMessage()); } } return outputFile; @@ -2397,7 +2403,7 @@ public class Manager implements Closeable { try { Files.delete(groupsFile.toPath()); } 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 { Files.delete(contactsFile.toPath()); } 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()); } } } diff --git a/src/main/java/org/asamk/signal/manager/PathConfig.java b/src/main/java/org/asamk/signal/manager/PathConfig.java index c0c9e1e7..ca750931 100644 --- a/src/main/java/org/asamk/signal/manager/PathConfig.java +++ b/src/main/java/org/asamk/signal/manager/PathConfig.java @@ -1,30 +1,34 @@ package org.asamk.signal.manager; +import java.io.File; + public class PathConfig { - private final String dataPath; - private final String attachmentsPath; - private final String avatarsPath; + private final File dataPath; + private final File attachmentsPath; + private final File avatarsPath; - public static PathConfig createDefault(final String settingsPath) { - return new PathConfig(settingsPath + "/data", settingsPath + "/attachments", settingsPath + "/avatars"); + public static PathConfig createDefault(final File settingsPath) { + 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.attachmentsPath = attachmentsPath; this.avatarsPath = avatarsPath; } public String getDataPath() { - return dataPath; + return dataPath.getPath(); } public String getAttachmentsPath() { - return attachmentsPath; + return attachmentsPath.getPath(); } public String getAvatarsPath() { - return avatarsPath; + return avatarsPath.getPath(); } } diff --git a/src/main/java/org/asamk/signal/manager/ProvisioningManager.java b/src/main/java/org/asamk/signal/manager/ProvisioningManager.java index eb70b351..f81cfa49 100644 --- a/src/main/java/org/asamk/signal/manager/ProvisioningManager.java +++ b/src/main/java/org/asamk/signal/manager/ProvisioningManager.java @@ -31,6 +31,7 @@ import org.whispersystems.signalservice.api.util.UptimeSleepTimer; import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration; import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider; +import java.io.File; import java.io.IOException; import java.util.concurrent.TimeoutException; @@ -45,7 +46,7 @@ public class ProvisioningManager { private final int registrationId; 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.serviceConfiguration = serviceConfiguration; this.userAgent = userAgent; diff --git a/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java b/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java index 6fd35003..5a88bc66 100644 --- a/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java +++ b/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java @@ -6,6 +6,7 @@ import org.asamk.signal.manager.GroupIdV2; import org.asamk.signal.manager.GroupLinkPassword; import org.asamk.signal.manager.GroupUtils; import org.asamk.signal.storage.groups.GroupInfoV2; +import org.asamk.signal.storage.profiles.SignalProfile; import org.asamk.signal.util.IOUtils; import org.signal.storageservice.protos.groups.AccessControl; 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.UuidCiphertext; 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.guava.Optional; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; @@ -44,6 +47,8 @@ import java.util.stream.Collectors; public class GroupHelper { + final static Logger logger = LoggerFactory.getLogger(GroupHelper.class); + private final ProfileKeyCredentialProvider profileKeyCredentialProvider; private final ProfileProvider profileProvider; @@ -78,7 +83,7 @@ public class GroupHelper { groupSecretParams); return groupsV2Api.getGroup(groupSecretParams, groupsV2AuthorizationString); } 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; } } @@ -111,11 +116,11 @@ public class GroupHelper { groupsV2Api.putNewGroup(newGroup, groupAuthForToday); decryptedGroup = groupsV2Api.getGroup(groupSecretParams, groupAuthForToday); } 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; } if (decryptedGroup == null) { - System.err.println("Failed to create V2 group!"); + logger.warn("Failed to create V2 group, unknown error!"); return null; } @@ -141,7 +146,7 @@ public class GroupHelper { final ProfileKeyCredential profileKeyCredential = profileKeyCredentialProvider.getProfileKeyCredential( selfAddressProvider.getSelfAddress()); 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; } @@ -165,22 +170,23 @@ public class GroupHelper { } private boolean areMembersValid(final Collection members) { - final int noUuidCapability = members.stream() + final Set noUuidCapability = members.stream() .filter(address -> !address.getUuid().isPresent()) - .collect(Collectors.toUnmodifiableSet()) - .size(); - if (noUuidCapability > 0) { - System.err.println("Cannot create a V2 group as " + noUuidCapability + " members don't have a UUID."); + .map(SignalServiceAddress::getLegacyIdentifier) + .collect(Collectors.toSet()); + if (noUuidCapability.size() > 0) { + logger.warn("Cannot create a V2 group as some members don't have a UUID: {}", + String.join(", ", noUuidCapability)); return false; } - final int noGv2Capability = members.stream() + final Set noGv2Capability = members.stream() .map(profileProvider::getProfile) .filter(profile -> profile != null && !profile.getCapabilities().gv2) - .collect(Collectors.toUnmodifiableSet()) - .size(); - if (noGv2Capability > 0) { - System.err.println("Cannot create a V2 group as " + noGv2Capability + " members don't support Groups V2."); + .collect(Collectors.toSet()); + if (noGv2Capability.size() > 0) { + logger.warn("Cannot create a V2 group as some members don't support Groups V2: {}", + noGv2Capability.stream().map(SignalProfile::getName).collect(Collectors.joining(", "))); return false; } @@ -219,7 +225,9 @@ public class GroupHelper { final GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); GroupsV2Operations.GroupOperations groupOperations = groupsV2Operations.forGroup(groupSecretParams); - if (!areMembersValid(newMembers)) return null; + if (!areMembersValid(newMembers)) { + throw new IOException("Failed to update group"); + } Set candidates = newMembers.stream() .map(member -> new GroupCandidate(member.getUuid().get(), diff --git a/src/main/java/org/asamk/signal/storage/SignalAccount.java b/src/main/java/org/asamk/signal/storage/SignalAccount.java index d3145ecd..e697efe3 100644 --- a/src/main/java/org/asamk/signal/storage/SignalAccount.java +++ b/src/main/java/org/asamk/signal/storage/SignalAccount.java @@ -29,6 +29,8 @@ import org.asamk.signal.util.IOUtils; import org.asamk.signal.util.Util; import org.signal.zkgroup.InvalidInputException; import org.signal.zkgroup.profiles.ProfileKey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.state.PreKeyRecord; import org.whispersystems.libsignal.state.SignedPreKeyRecord; @@ -53,6 +55,8 @@ import java.util.stream.Collectors; public class SignalAccount implements Closeable { + final static Logger logger = LoggerFactory.getLogger(SignalAccount.class); + private final ObjectMapper jsonProcessor = new ObjectMapper(); private final FileChannel fileChannel; private final FileLock lock; @@ -357,7 +361,7 @@ public class SignalAccount implements Closeable { } } } 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(); FileLock lock = fileChannel.tryLock(); 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(); - System.err.println("Config file lock acquired."); + logger.info("Config file lock acquired."); } return new Pair<>(fileChannel, lock); } diff --git a/src/main/java/org/asamk/signal/storage/groups/JsonGroupStore.java b/src/main/java/org/asamk/signal/storage/groups/JsonGroupStore.java index 6f0f3c04..18bf5ed0 100644 --- a/src/main/java/org/asamk/signal/storage/groups/JsonGroupStore.java +++ b/src/main/java/org/asamk/signal/storage/groups/JsonGroupStore.java @@ -21,6 +21,8 @@ import org.asamk.signal.util.IOUtils; import org.signal.storageservice.protos.groups.local.DecryptedGroup; import org.signal.zkgroup.InvalidInputException; import org.signal.zkgroup.groups.GroupMasterKey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.util.Base64; import java.io.File; @@ -35,6 +37,8 @@ import java.util.Map; public class JsonGroupStore { + final static Logger logger = LoggerFactory.getLogger(JsonGroupStore.class); + private static final ObjectMapper jsonProcessor = new ObjectMapper(); public File groupCachePath; @@ -63,7 +67,7 @@ public class JsonGroupStore { groupFileLegacy.delete(); } } catch (IOException e) { - System.err.println("Failed to cache group, ignoring ..."); + logger.warn("Failed to cache group, ignoring: {}", e.getMessage()); } } } diff --git a/src/main/java/org/asamk/signal/storage/protocol/JsonIdentityKeyStore.java b/src/main/java/org/asamk/signal/storage/protocol/JsonIdentityKeyStore.java index 0095e6d2..29160cf1 100644 --- a/src/main/java/org/asamk/signal/storage/protocol/JsonIdentityKeyStore.java +++ b/src/main/java/org/asamk/signal/storage/protocol/JsonIdentityKeyStore.java @@ -10,6 +10,8 @@ import com.fasterxml.jackson.databind.SerializerProvider; import org.asamk.signal.manager.TrustLevel; import org.asamk.signal.util.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.InvalidKeyException; @@ -27,6 +29,8 @@ import java.util.UUID; public class JsonIdentityKeyStore implements IdentityKeyStore { + final static Logger logger = LoggerFactory.getLogger(JsonIdentityKeyStore.class); + private final List identities = new ArrayList<>(); private final IdentityKeyPair identityKeyPair; @@ -219,7 +223,7 @@ public class JsonIdentityKeyStore implements IdentityKeyStore { .asLong()) : new Date(); keyStore.saveIdentity(serviceAddress, id, trustLevel, added); } 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()); } } } diff --git a/src/main/java/org/asamk/signal/storage/protocol/JsonPreKeyStore.java b/src/main/java/org/asamk/signal/storage/protocol/JsonPreKeyStore.java index dea1996d..523809c1 100644 --- a/src/main/java/org/asamk/signal/storage/protocol/JsonPreKeyStore.java +++ b/src/main/java/org/asamk/signal/storage/protocol/JsonPreKeyStore.java @@ -8,6 +8,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.libsignal.InvalidKeyIdException; import org.whispersystems.libsignal.state.PreKeyRecord; import org.whispersystems.libsignal.state.PreKeyStore; @@ -19,6 +21,8 @@ import java.util.Map; class JsonPreKeyStore implements PreKeyStore { + final static Logger logger = LoggerFactory.getLogger(JsonPreKeyStore.class); + private final Map store = new HashMap<>(); public JsonPreKeyStore() { @@ -72,7 +76,7 @@ class JsonPreKeyStore implements PreKeyStore { try { preKeyMap.put(preKeyId, Base64.decode(preKey.get("record").asText())); } 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()); } } } diff --git a/src/main/java/org/asamk/signal/storage/protocol/JsonSessionStore.java b/src/main/java/org/asamk/signal/storage/protocol/JsonSessionStore.java index fae72bae..24e4594e 100644 --- a/src/main/java/org/asamk/signal/storage/protocol/JsonSessionStore.java +++ b/src/main/java/org/asamk/signal/storage/protocol/JsonSessionStore.java @@ -9,6 +9,8 @@ import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import org.asamk.signal.util.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.libsignal.SignalProtocolAddress; import org.whispersystems.libsignal.state.SessionRecord; import org.whispersystems.libsignal.state.SessionStore; @@ -24,6 +26,8 @@ import java.util.UUID; class JsonSessionStore implements SessionStore { + final static Logger logger = LoggerFactory.getLogger(JsonSessionStore.class); + private final List sessions = new ArrayList<>(); private SignalServiceAddressResolver resolver; @@ -51,7 +55,7 @@ class JsonSessionStore implements SessionStore { try { return new SessionRecord(info.sessionRecord); } 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(); info.sessionRecord = sessionRecord.serialize(); return sessionRecord; @@ -151,7 +155,7 @@ class JsonSessionStore implements SessionStore { SessionInfo sessionInfo = new SessionInfo(serviceAddress, deviceId, Base64.decode(record)); sessionStore.sessions.add(sessionInfo); } 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()); } } } diff --git a/src/main/java/org/asamk/signal/storage/protocol/JsonSignedPreKeyStore.java b/src/main/java/org/asamk/signal/storage/protocol/JsonSignedPreKeyStore.java index 255dd4e0..7accf5a1 100644 --- a/src/main/java/org/asamk/signal/storage/protocol/JsonSignedPreKeyStore.java +++ b/src/main/java/org/asamk/signal/storage/protocol/JsonSignedPreKeyStore.java @@ -8,6 +8,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.whispersystems.libsignal.InvalidKeyIdException; import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.libsignal.state.SignedPreKeyStore; @@ -21,6 +23,8 @@ import java.util.Map; class JsonSignedPreKeyStore implements SignedPreKeyStore { + final static Logger logger = LoggerFactory.getLogger(JsonSignedPreKeyStore.class); + private final Map store = new HashMap<>(); public JsonSignedPreKeyStore() { @@ -89,7 +93,7 @@ class JsonSignedPreKeyStore implements SignedPreKeyStore { try { preKeyMap.put(preKeyId, Base64.decode(preKey.get("record").asText())); } 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()); } } }