X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/be963ed49b6b32ab90707c453f8ce2c85b72e428..4730e9cbc7e440b8ca975fa4713a6e15fe0597c7:/src/main/java/org/asamk/signal/Manager.java diff --git a/src/main/java/org/asamk/signal/Manager.java b/src/main/java/org/asamk/signal/Manager.java index a6dfcae5..b20ca002 100644 --- a/src/main/java/org/asamk/signal/Manager.java +++ b/src/main/java/org/asamk/signal/Manager.java @@ -16,6 +16,10 @@ */ package org.asamk.signal; +import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE; +import static java.nio.file.attribute.PosixFilePermission.OWNER_READ; +import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE; + import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.core.JsonGenerator; @@ -25,9 +29,67 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.node.ObjectNode; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InvalidObjectException; +import java.io.OutputStream; +import java.io.RandomAccessFile; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + import org.apache.http.util.TextUtils; import org.asamk.Signal; -import org.whispersystems.libsignal.*; +import org.asamk.signal.storage.contacts.ContactInfo; +import org.asamk.signal.storage.contacts.JsonContactsStore; +import org.asamk.signal.storage.groups.GroupInfo; +import org.asamk.signal.storage.groups.JsonGroupStore; +import org.asamk.signal.storage.protocol.JsonIdentityKeyStore; +import org.asamk.signal.storage.protocol.JsonSignalProtocolStore; +import org.asamk.signal.storage.threads.JsonThreadStore; +import org.asamk.signal.storage.threads.ThreadInfo; +import org.asamk.signal.util.Base64; +import org.asamk.signal.util.Util; +import org.whispersystems.libsignal.DuplicateMessageException; +import org.whispersystems.libsignal.IdentityKey; +import org.whispersystems.libsignal.IdentityKeyPair; +import org.whispersystems.libsignal.InvalidKeyException; +import org.whispersystems.libsignal.InvalidKeyIdException; +import org.whispersystems.libsignal.InvalidMessageException; +import org.whispersystems.libsignal.InvalidVersionException; +import org.whispersystems.libsignal.LegacyMessageException; +import org.whispersystems.libsignal.NoSessionException; import org.whispersystems.libsignal.ecc.Curve; import org.whispersystems.libsignal.ecc.ECKeyPair; import org.whispersystems.libsignal.ecc.ECPublicKey; @@ -44,37 +106,35 @@ import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.crypto.SignalServiceCipher; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; -import org.whispersystems.signalservice.api.messages.*; -import org.whispersystems.signalservice.api.messages.multidevice.*; +import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; +import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; +import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream; +import org.whispersystems.signalservice.api.messages.SignalServiceContent; +import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; +import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; +import org.whispersystems.signalservice.api.messages.SignalServiceGroup; +import org.whispersystems.signalservice.api.messages.multidevice.DeviceContact; +import org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsInputStream; +import org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsOutputStream; +import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroup; +import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsInputStream; +import org.whispersystems.signalservice.api.messages.multidevice.DeviceGroupsOutputStream; +import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo; +import org.whispersystems.signalservice.api.messages.multidevice.RequestMessage; +import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.push.ContactTokenDetails; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.TrustStore; -import org.whispersystems.signalservice.api.push.exceptions.*; +import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; +import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions; +import org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException; +import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; +import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException; import org.whispersystems.signalservice.api.util.InvalidNumberException; import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import org.whispersystems.signalservice.internal.push.SignalServiceProtos; import org.whispersystems.signalservice.internal.push.SignalServiceUrl; -import java.io.*; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.nio.channels.Channels; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.PosixFilePermission; -import java.nio.file.attribute.PosixFilePermissions; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import static java.nio.file.attribute.PosixFilePermission.*; - class Manager implements Signal { private final static String URL = "https://textsecure-service.whispersystems.org"; private final static TrustStore TRUST_STORE = new WhisperTrustStore(); @@ -356,6 +416,10 @@ class Manager implements Signal { save(); } + public void updateAccountAttributes() throws IOException { + accountManager.setAccountAttributes(signalingKey, signalProtocolStore.getLocalRegistrationId(), false, false,true); + } + public void unregister() throws IOException { // When setting an empty GCM id, the Signal-Server also sets the fetchesMessages property to false. // If this is the master device, other users can't send messages to this number anymore. @@ -503,7 +567,7 @@ class Manager implements Signal { public void verifyAccount(String verificationCode) throws IOException { verificationCode = verificationCode.replace("-", ""); signalingKey = Util.getSecret(52); - accountManager.verifyAccountWithCode(verificationCode, signalingKey, signalProtocolStore.getLocalRegistrationId(), false, true); + accountManager.verifyAccountWithCode(verificationCode, signalingKey, signalProtocolStore.getLocalRegistrationId(), false, false,true); //accountManager.setGcmId(Optional.of(GoogleCloudMessaging.getInstance(this).register(REGISTRATION_ID))); registered = true; @@ -576,6 +640,10 @@ class Manager implements Signal { } throw new NotAGroupMemberException(groupId, g.name); } + + public List getGroups() { + return groupStore.getGroups(); + } @Override public void sendGroupMessage(String messageText, List attachments, @@ -771,6 +839,65 @@ class Manager implements Signal { sendMessage(messageBuilder, recipients); } + @Override + public String getContactName(String number) { + ContactInfo contact = contactStore.getContact(number); + if (contact == null) { + return ""; + } else { + return contact.name; + } + } + + @Override + public void setContactName(String number, String name) { + ContactInfo contact = contactStore.getContact(number); + if (contact == null) { + contact = new ContactInfo(); + contact.number = number; + System.out.println("Add contact " + number + " named " + name); + } else { + System.out.println("Updating contact " + number + " name " + contact.name + " -> " + name); + } + contact.name = name; + contactStore.updateContact(contact); + save(); + } + + @Override + public String getGroupName(byte[] groupId) { + GroupInfo group = getGroup(groupId); + if (group == null) { + return ""; + } else { + return group.name; + } + } + + @Override + public List getGroupMembers(byte[] groupId) { + GroupInfo group = getGroup(groupId); + if (group == null) { + return new ArrayList(); + } else { + return new ArrayList(group.members); + } + } + + @Override + public void updateGroup(byte[] groupId, String name, List members, String avatar) throws IOException, EncapsulatedExceptions, GroupNotFoundException, AttachmentInvalidException { + if (name.isEmpty()) { + name = null; + } + if (members.size() == 0) { + members = null; + } + if (avatar.isEmpty()) { + avatar = null; + } + sendUpdateGroupMessage(groupId, name, members, avatar); + } + private void requestSyncGroups() throws IOException { SignalServiceProtos.SyncMessage.Request r = SignalServiceProtos.SyncMessage.Request.newBuilder().setType(SignalServiceProtos.SyncMessage.Request.Type.GROUPS).build(); SignalServiceSyncMessage message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); @@ -1465,11 +1592,11 @@ class Manager implements Signal { return false; } for (JsonIdentityKeyStore.Identity id : ids) { - if (!Arrays.equals(id.identityKey.serialize(), fingerprint)) { + if (!Arrays.equals(id.getIdentityKey().serialize(), fingerprint)) { continue; } - signalProtocolStore.saveIdentity(name, id.identityKey, TrustLevel.TRUSTED_VERIFIED); + signalProtocolStore.saveIdentity(name, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); save(); return true; } @@ -1488,11 +1615,11 @@ class Manager implements Signal { return false; } for (JsonIdentityKeyStore.Identity id : ids) { - if (!safetyNumber.equals(computeSafetyNumber(name, id.identityKey))) { + if (!safetyNumber.equals(computeSafetyNumber(name, id.getIdentityKey()))) { continue; } - signalProtocolStore.saveIdentity(name, id.identityKey, TrustLevel.TRUSTED_VERIFIED); + signalProtocolStore.saveIdentity(name, id.getIdentityKey(), TrustLevel.TRUSTED_VERIFIED); save(); return true; } @@ -1510,8 +1637,8 @@ class Manager implements Signal { return false; } for (JsonIdentityKeyStore.Identity id : ids) { - if (id.trustLevel == TrustLevel.UNTRUSTED) { - signalProtocolStore.saveIdentity(name, id.identityKey, TrustLevel.TRUSTED_UNVERIFIED); + if (id.getTrustLevel() == TrustLevel.UNTRUSTED) { + signalProtocolStore.saveIdentity(name, id.getIdentityKey(), TrustLevel.TRUSTED_UNVERIFIED); } } save();