Revert "track attachment data (#671 and #316)"

This reverts commit 8aed357994.
This commit is contained in:
John Freed 2021-08-12 14:38:47 +02:00
parent 0f437dbfd1
commit 5059925b22
20 changed files with 52 additions and 519 deletions

3
.gitignore vendored
View file

@ -11,6 +11,3 @@ local.properties
.settings/ .settings/
out/ out/
.DS_Store .DS_Store
.git/
signal-cli
bin/

View file

@ -1,7 +1,7 @@
# signal-cli # signal-cli
signal-cli is a commandline interface for [libsignal-service-java](https://github.com/WhisperSystems/libsignal-service-java). It supports registering, verifying, sending and receiving messages. signal-cli is a commandline interface for [libsignal-service-java](https://github.com/WhisperSystems/libsignal-service-java). It supports registering, verifying, sending and receiving messages.
To be able to link to an existing Signal-Android/signal-cli instance, signal-cli uses a [patched libsignal-service-java](https://github.com/AsamK/libsignal-service-java), because libsignal-service-java does not yet support [provisioning as a secondary device](https://github.com/WhisperSystems/libsignal-service-java/pull/21). To be able to link to an existing Signal-Android/signal-cli instance, signal-cli uses a [patched libsignal-service-java](https://github.com/AsamK/libsignal-service-java), because libsignal-service-java does not yet support [provisioning as a slave device](https://github.com/WhisperSystems/libsignal-service-java/pull/21).
For registering you need a phone number where you can receive SMS or incoming calls. For registering you need a phone number where you can receive SMS or incoming calls.
signal-cli is primarily intended to be used on servers to notify admins of important events. For this use-case, it has a dbus interface ([man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-dbus.5.adoc)), that can be used to send messages from any programming language that has dbus bindings. signal-cli is primarily intended to be used on servers to notify admins of important events. For this use-case, it has a dbus interface ([man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-dbus.5.adoc)), that can be used to send messages from any programming language that has dbus bindings.

View file

@ -5,7 +5,7 @@ plugins {
`check-lib-versions` `check-lib-versions`
} }
version = "0.8.6" version = "0.8.5"
java { java {
sourceCompatibility = JavaVersion.VERSION_11 sourceCompatibility = JavaVersion.VERSION_11

View file

@ -1274,7 +1274,7 @@ public class Manager implements Closeable {
) throws IOException, AttachmentInvalidException, InvalidNumberException { ) throws IOException, AttachmentInvalidException, InvalidNumberException {
final var messageBuilder = SignalServiceDataMessage.newBuilder().withBody(messageText); final var messageBuilder = SignalServiceDataMessage.newBuilder().withBody(messageText);
if (attachments != null) { if (attachments != null) {
List<SignalServiceAttachment> attachmentStreams = AttachmentUtils.getSignalServiceAttachments(attachments); var attachmentStreams = AttachmentUtils.getSignalServiceAttachments(attachments);
// Upload attachments here, so we only upload once even for multiple recipients // Upload attachments here, so we only upload once even for multiple recipients
var messageSender = createMessageSender(); var messageSender = createMessageSender();

View file

@ -11,7 +11,6 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.net.URL;
public class AttachmentUtils { public class AttachmentUtils {
@ -22,13 +21,8 @@ public class AttachmentUtils {
for (var attachment : attachments) { for (var attachment : attachments) {
try { try {
signalServiceAttachments.add(createAttachment(new File(attachment))); signalServiceAttachments.add(createAttachment(new File(attachment)));
} catch (IOException f) { } catch (IOException e) {
// no such file, send it as URL throw new AttachmentInvalidException(attachment, e);
try {
signalServiceAttachments.add(createAttachment(new URL(attachment)));
} catch (IOException e) {
throw new AttachmentInvalidException(attachment, e);
}
} }
} }
} }
@ -40,39 +34,25 @@ public class AttachmentUtils {
return createAttachment(streamDetails, Optional.of(attachmentFile.getName())); return createAttachment(streamDetails, Optional.of(attachmentFile.getName()));
} }
public static SignalServiceAttachmentStream createAttachment(URL aURL) throws IOException {
final var streamDetails = Utils.createStreamDetailsFromURL(aURL);
String path = aURL.getPath();
String name = path.substring(path.lastIndexOf('/') + 1);
return createAttachment(streamDetails, Optional.of(name));
}
public static SignalServiceAttachmentStream createAttachment( public static SignalServiceAttachmentStream createAttachment(
StreamDetails streamDetails, Optional<String> name StreamDetails streamDetails, Optional<String> name
) { ) {
// TODO maybe add a parameter to set the voiceNote, borderless, preview, width, height, caption, blurHash options // TODO mabybe add a parameter to set the voiceNote, borderless, preview, width, height and caption option
final var uploadTimestamp = System.currentTimeMillis(); final var uploadTimestamp = System.currentTimeMillis();
boolean voicenote = false;
boolean borderless = false;
Optional<byte[]> preview = Optional.absent(); Optional<byte[]> preview = Optional.absent();
int width = 0;
int height = 0;
Optional<String> caption = Optional.absent(); Optional<String> caption = Optional.absent();
Optional<String> blurHash = Optional.absent(); Optional<String> blurHash = Optional.absent();
final Optional<ResumableUploadSpec> resumableUploadSpec = Optional.absent(); final Optional<ResumableUploadSpec> resumableUploadSpec = Optional.absent();
//ProgressListener listener = null; //Android OS
//CancellationSignal cancellationSignal = null; //Android OS; Signal developers misspelled class name
return new SignalServiceAttachmentStream(streamDetails.getStream(), return new SignalServiceAttachmentStream(streamDetails.getStream(),
streamDetails.getContentType(), streamDetails.getContentType(),
streamDetails.getLength(), streamDetails.getLength(),
name, name,
voicenote, false,
borderless, false,
false, false,
preview, preview,
width, 0,
height, 0,
uploadTimestamp, uploadTimestamp,
caption, caption,
blurHash, blurHash,

View file

@ -11,7 +11,6 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.nio.file.Files; import java.nio.file.Files;
@ -37,13 +36,6 @@ public class Utils {
return new StreamDetails(stream, mime, size); return new StreamDetails(stream, mime, size);
} }
public static StreamDetails createStreamDetailsFromURL(URL aURL) throws IOException {
InputStream stream = aURL.openStream();
final var mime = aURL.openConnection().getContentType();
final var size = aURL.openConnection().getContentLengthLong();
return new StreamDetails(stream, mime, size);
}
public static String computeSafetyNumber( public static String computeSafetyNumber(
boolean isUuidCapable, boolean isUuidCapable,
SignalServiceAddress ownAddress, SignalServiceAddress ownAddress,

Binary file not shown.

View file

@ -4,7 +4,6 @@ import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.exceptions.DBusExecutionException; import org.freedesktop.dbus.exceptions.DBusExecutionException;
import org.freedesktop.dbus.interfaces.DBusInterface; import org.freedesktop.dbus.interfaces.DBusInterface;
import org.freedesktop.dbus.messages.DBusSignal; import org.freedesktop.dbus.messages.DBusSignal;
import org.asamk.signal.dbus.DbusAttachment;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -16,21 +15,12 @@ import java.util.Map;
*/ */
public interface Signal extends DBusInterface { public interface Signal extends DBusInterface {
long sendMessage(
long sendMessageWithDBusAttachments( String message, List<String> attachments, String recipient
String message, List<DbusAttachment> dBusAttachments, String recipient
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
long sendMessageWithDBusAttachments(
String message, List<DbusAttachment> dBusAttachments, List<String> recipients
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity; ) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
long sendMessage( long sendMessage(
String message, List<String> attachmentNames, String recipient String message, List<String> attachments, List<String> recipients
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
long sendMessage(
String message, List<String> attachmentNames, List<String> recipients
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity; ) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
long sendRemoteDeleteMessage( long sendRemoteDeleteMessage(
@ -54,21 +44,13 @@ public interface Signal extends DBusInterface {
) throws Error.InvalidNumber, Error.Failure; ) throws Error.InvalidNumber, Error.Failure;
long sendNoteToSelfMessage( long sendNoteToSelfMessage(
String message, List<String> attachmentNames String message, List<String> attachments
) throws Error.AttachmentInvalid, Error.Failure;
long sendNoteToSelfMessageWithDBusAttachments(
String message, List<DbusAttachment> dBusAttachments
) throws Error.AttachmentInvalid, Error.Failure; ) throws Error.AttachmentInvalid, Error.Failure;
void sendEndSessionMessage(List<String> recipients) throws Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity; void sendEndSessionMessage(List<String> recipients) throws Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
long sendGroupMessage( long sendGroupMessage(
String message, List<String> attachmentNames, byte[] groupId String message, List<String> attachments, byte[] groupId
) throws Error.GroupNotFound, Error.Failure, Error.AttachmentInvalid;
long sendGroupMessageWithDBusAttachments(
String message, List<DbusAttachment> dBusAttachments, byte[] groupId
) throws Error.GroupNotFound, Error.Failure, Error.AttachmentInvalid; ) throws Error.GroupNotFound, Error.Failure, Error.AttachmentInvalid;
long sendGroupMessageReaction( long sendGroupMessageReaction(
@ -79,8 +61,6 @@ public interface Signal extends DBusInterface {
void setContactName(String number, String name) throws Error.InvalidNumber; void setContactName(String number, String name) throws Error.InvalidNumber;
void setExpirationTimer(final String number, final int expiration) throws Error.InvalidNumber;
void setContactBlocked(String number, boolean blocked) throws Error.InvalidNumber; void setContactBlocked(String number, boolean blocked) throws Error.InvalidNumber;
void setGroupBlocked(byte[] groupId, boolean blocked) throws Error.GroupNotFound; void setGroupBlocked(byte[] groupId, boolean blocked) throws Error.GroupNotFound;
@ -133,7 +113,7 @@ public interface Signal extends DBusInterface {
private final String sender; private final String sender;
private final byte[] groupId; private final byte[] groupId;
private final String message; private final String message;
private final List<DbusAttachment> dBusAttachments; private final List<String> attachments;
public MessageReceived( public MessageReceived(
String objectpath, String objectpath,
@ -141,14 +121,14 @@ public interface Signal extends DBusInterface {
String sender, String sender,
byte[] groupId, byte[] groupId,
String message, String message,
List<DbusAttachment> dBusAttachments List<String> attachments
) throws DBusException { ) throws DBusException {
super(objectpath, timestamp, sender, groupId, message, dBusAttachments); super(objectpath, timestamp, sender, groupId, message, attachments);
this.timestamp = timestamp; this.timestamp = timestamp;
this.sender = sender; this.sender = sender;
this.groupId = groupId; this.groupId = groupId;
this.message = message; this.message = message;
this.dBusAttachments = dBusAttachments; this.attachments = attachments;
} }
public long getTimestamp() { public long getTimestamp() {
@ -167,10 +147,9 @@ public interface Signal extends DBusInterface {
return message; return message;
} }
public List<DbusAttachment> getAttachments() { public List<String> getAttachments() {
return dBusAttachments; return attachments;
} }
} }
class ReceiptReceived extends DBusSignal { class ReceiptReceived extends DBusSignal {
@ -200,7 +179,7 @@ public interface Signal extends DBusInterface {
private final String destination; private final String destination;
private final byte[] groupId; private final byte[] groupId;
private final String message; private final String message;
private final List<DbusAttachment> dBusAttachments; private final List<String> attachments;
public SyncMessageReceived( public SyncMessageReceived(
String objectpath, String objectpath,
@ -209,15 +188,15 @@ public interface Signal extends DBusInterface {
String destination, String destination,
byte[] groupId, byte[] groupId,
String message, String message,
List<DbusAttachment> dBusAttachments List<String> attachments
) throws DBusException { ) throws DBusException {
super(objectpath, timestamp, source, destination, groupId, message, dBusAttachments); super(objectpath, timestamp, source, destination, groupId, message, attachments);
this.timestamp = timestamp; this.timestamp = timestamp;
this.source = source; this.source = source;
this.destination = destination; this.destination = destination;
this.groupId = groupId; this.groupId = groupId;
this.message = message; this.message = message;
this.dBusAttachments = dBusAttachments; this.attachments = attachments;
} }
public long getTimestamp() { public long getTimestamp() {
@ -240,8 +219,8 @@ public interface Signal extends DBusInterface {
return message; return message;
} }
public List<DbusAttachment> getAttachments() { public List<String> getAttachments() {
return dBusAttachments; return attachments;
} }
} }

View file

@ -28,6 +28,8 @@ public interface SignalControl extends DBusInterface {
String version(); String version();
List<DBusPath> listAccounts();
String getObjectPath(); String getObjectPath();
interface Error { interface Error {

View file

@ -163,7 +163,7 @@ public class App {
username = usernames.get(0); username = usernames.get(0);
} else if (!PhoneNumberFormatter.isValidNumber(username, null)) { } else if (!PhoneNumberFormatter.isValidNumber(username, null)) {
throw new UserErrorException("Invalid username (phone number), make sure you include a plus sign (+) followed by the country code."); throw new UserErrorException("Invalid username (phone number), make sure you include the country code.");
} }
if (command instanceof RegistrationCommand) { if (command instanceof RegistrationCommand) {
@ -264,7 +264,6 @@ public class App {
try { try {
manager = Manager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT); manager = Manager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
} catch (NotRegisteredException e) { } catch (NotRegisteredException e) {
logger.debug("dataPath=" + dataPath + " serviceEnvironment=" + serviceEnvironment, e);
throw new UserErrorException("User " + username + " is not registered."); throw new UserErrorException("User " + username + " is not registered.");
} catch (Throwable e) { } catch (Throwable e) {
logger.debug("Loading state file failed", e); logger.debug("Loading state file failed", e);

View file

@ -1,7 +1,6 @@
package org.asamk.signal; package org.asamk.signal;
import org.asamk.Signal; import org.asamk.Signal;
import org.asamk.signal.dbus.DbusAttachment;
import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.groups.GroupUtils; import org.asamk.signal.manager.groups.GroupUtils;
import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.connections.impl.DBusConnection;
@ -10,7 +9,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceContent;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
import org.whispersystems.signalservice.api.messages.SignalServiceGroup; import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -73,15 +71,12 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
|| message.getGroupContext().get().getGroupV1Type() == SignalServiceGroup.Type.DELIVER || message.getGroupContext().get().getGroupV1Type() == SignalServiceGroup.Type.DELIVER
)) { )) {
try { try {
List<SignalServiceAttachment> attachments = JsonDbusReceiveMessageHandler.getAttachments(message);
List<DbusAttachment> dBusAttachments = JsonDbusReceiveMessageHandler.convertSignalAttachmentsToDbus(attachments);
conn.sendMessage(new Signal.MessageReceived(objectPath, conn.sendMessage(new Signal.MessageReceived(objectPath,
message.getTimestamp(), message.getTimestamp(),
getLegacyIdentifier(sender), getLegacyIdentifier(sender),
groupId != null ? groupId : new byte[0], groupId != null ? groupId : new byte[0],
message.getBody().isPresent() ? message.getBody().get() : "", message.getBody().isPresent() ? message.getBody().get() : "",
dBusAttachments JsonDbusReceiveMessageHandler.getAttachments(message, m)));
));
} catch (DBusException e) { } catch (DBusException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -98,8 +93,6 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
var groupId = getGroupId(message); var groupId = getGroupId(message);
try { try {
List<SignalServiceAttachment> attachments = JsonDbusReceiveMessageHandler.getAttachments(message);
List<DbusAttachment> dBusAttachments = JsonDbusReceiveMessageHandler.convertSignalAttachmentsToDbus(attachments);
conn.sendMessage(new Signal.SyncMessageReceived(objectPath, conn.sendMessage(new Signal.SyncMessageReceived(objectPath,
transcript.getTimestamp(), transcript.getTimestamp(),
getLegacyIdentifier(sender), getLegacyIdentifier(sender),
@ -108,8 +101,7 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
: "", : "",
groupId != null ? groupId : new byte[0], groupId != null ? groupId : new byte[0],
message.getBody().isPresent() ? message.getBody().get() : "", message.getBody().isPresent() ? message.getBody().get() : "",
dBusAttachments JsonDbusReceiveMessageHandler.getAttachments(message, m)));
));
} catch (DBusException e) { } catch (DBusException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -124,7 +116,7 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
.serialize() : null; .serialize() : null;
} }
static private List<String> getAttachmentNames(SignalServiceDataMessage message, Manager m) { static private List<String> getAttachments(SignalServiceDataMessage message, Manager m) {
var attachments = new ArrayList<String>(); var attachments = new ArrayList<String>();
if (message.getAttachments().isPresent()) { if (message.getAttachments().isPresent()) {
for (var attachment : message.getAttachments().get()) { for (var attachment : message.getAttachments().get()) {
@ -136,34 +128,10 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
return attachments; return attachments;
} }
static private List<SignalServiceAttachment> getAttachments(SignalServiceDataMessage message) {
var attachments = new ArrayList<SignalServiceAttachment>();
if (message.getAttachments().isPresent()) {
for (var attachment : message.getAttachments().get()) {
if (attachment.isPointer()) {
attachments.add(attachment);
}
}
}
return attachments;
}
@Override @Override
public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) { public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
super.handleMessage(envelope, content, exception); super.handleMessage(envelope, content, exception);
sendReceivedMessageToDbus(envelope, content, conn, objectPath, m); sendReceivedMessageToDbus(envelope, content, conn, objectPath, m);
} }
static private List<DbusAttachment> convertSignalAttachmentsToDbus(List<SignalServiceAttachment> attachments) {
ArrayList<DbusAttachment> dBusAttachments = new ArrayList<>();
if (!attachments.isEmpty()) {
for (SignalServiceAttachment attachment : attachments) {
DbusAttachment dBusAttachment = new DbusAttachment(attachment);
dBusAttachments.add(dBusAttachment);
}
}
return dBusAttachments;
}
} }

View file

@ -646,9 +646,6 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
if (pointer.getCaption().isPresent()) { if (pointer.getCaption().isPresent()) {
writer.println("Caption: {}", pointer.getCaption().get()); writer.println("Caption: {}", pointer.getCaption().get());
} }
if (pointer.getBlurHash().isPresent()) {
writer.println("Blur Hash: {}", pointer.getBlurHash().get());
}
if (pointer.getFileName().isPresent()) { if (pointer.getFileName().isPresent()) {
writer.println("Filename: {}", pointer.getFileName().get()); writer.println("Filename: {}", pointer.getFileName().get());
} }

View file

@ -65,12 +65,7 @@ public class DaemonCommand implements MultiLocalCommand {
var objectPath = DbusConfig.getObjectPath(); var objectPath = DbusConfig.getObjectPath();
var t = run(conn, objectPath, m, ignoreAttachments); var t = run(conn, objectPath, m, ignoreAttachments);
try { conn.requestBusName(DbusConfig.getBusname());
conn.requestBusName(DbusConfig.getBusname());
} catch (DBusException e) {
logger.error("Dbus request command failed", e);
throw new UnexpectedErrorException("Dbus request command failed");
}
try { try {
t.join(); t.join();

View file

@ -12,7 +12,6 @@ import org.asamk.signal.commands.exceptions.CommandException;
import org.asamk.signal.commands.exceptions.UnexpectedErrorException; import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException; import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.dbus.DbusAttachment;
import org.asamk.signal.dbus.DbusSignalImpl; import org.asamk.signal.dbus.DbusSignalImpl;
import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupIdFormatException;
@ -22,11 +21,9 @@ import org.freedesktop.dbus.errors.UnknownObject;
import org.freedesktop.dbus.exceptions.DBusExecutionException; import org.freedesktop.dbus.exceptions.DBusExecutionException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -94,17 +91,9 @@ public class SendCommand implements DbusCommand, JsonRpcLocalCommand {
} }
} }
List<String> attachmentNames = ns.getList("attachment"); List<String> attachments = ns.getList("attachment");
if (attachmentNames == null) { if (attachments == null) {
attachmentNames = List.of(); attachments = List.of();
}
ArrayList<DbusAttachment> dBusAttachments = new ArrayList<>();
if (!attachmentNames.isEmpty()) {
for (var attachmentName : attachmentNames) {
DbusAttachment dBusAttachment = new DbusAttachment(attachmentName);
dBusAttachments.add(dBusAttachment);
}
} }
if (groupIdString != null) { if (groupIdString != null) {
@ -116,7 +105,7 @@ public class SendCommand implements DbusCommand, JsonRpcLocalCommand {
} }
try { try {
var timestamp = signal.sendGroupMessage(messageText, attachmentNames, groupId); var timestamp = signal.sendGroupMessage(messageText, attachments, groupId);
outputResult(timestamp); outputResult(timestamp);
return; return;
} catch (DBusExecutionException e) { } catch (DBusExecutionException e) {
@ -126,25 +115,25 @@ public class SendCommand implements DbusCommand, JsonRpcLocalCommand {
if (isNoteToSelf) { if (isNoteToSelf) {
try { try {
var timestamp = signal.sendNoteToSelfMessage(messageText, attachmentNames); var timestamp = signal.sendNoteToSelfMessage(messageText, attachments);
outputResult(timestamp); outputResult(timestamp);
return; return;
} catch (Signal.Error.UntrustedIdentity e) { } catch (Signal.Error.UntrustedIdentity e) {
throw new UntrustedKeyErrorException("Failed to send note to self message: " + e.getMessage()); throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage());
} catch (DBusExecutionException e) { } catch (DBusExecutionException e) {
throw new UnexpectedErrorException("Failed to send note to self message: " + e.getMessage()); throw new UnexpectedErrorException("Failed to send note to self message: " + e.getMessage());
} }
} }
try { try {
var timestamp = signal.sendMessageWithDBusAttachments(messageText, dBusAttachments, recipients); var timestamp = signal.sendMessage(messageText, attachments, recipients);
outputResult(timestamp); outputResult(timestamp);
} catch (UnknownObject e) { } catch (UnknownObject e) {
throw new UserErrorException("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage()); throw new UserErrorException("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage());
} catch (Signal.Error.UntrustedIdentity e) { } catch (Signal.Error.UntrustedIdentity e) {
throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage()); throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage());
} catch (DBusExecutionException e) { } catch (DBusExecutionException e) {
throw new UnexpectedErrorException("Failed to send message, did not find attachment: " + e.getMessage()); throw new UnexpectedErrorException("Failed to send message: " + e.getMessage());
} }
} }

View file

@ -1,238 +0,0 @@
package org.asamk.signal.dbus;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
import org.whispersystems.signalservice.api.util.StreamDetails;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.annotations.Position;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import org.asamk.signal.manager.util.Utils;
import org.freedesktop.dbus.Struct;
public final class DbusAttachment extends Struct
{
@Position(0)
private String contentType;
@Position(1)
private String fileName;
@Position(2)
private String id;
@Position(3)
private Long size;
@Position(4)
private Integer keyLength;
@Position(5)
private boolean voiceNote;
@Position(6)
private Integer width;
@Position(7)
private Integer height;
@Position(8)
private String caption;
@Position(9)
private String blurHash;
/*
* API = 2.15.3 from https://github.com/Turasa/libsignal-service-java (nonstandard)
public SignalServiceAttachmentStream(InputStream inputStream,
String contentType,
long length,
Optional<String> fileName,
boolean voiceNote,
boolean borderless,
boolean gif, //nonstandard
Optional<byte[]> preview,
int width,
int height,
long uploadTimestamp,
Optional<String> caption,
Optional<String> blurHash,
ProgressListener listener, //Android OS
CancellationSignal cancellationSignal, //Android OS, Signal developers misspelled class name
Optional<ResumableUploadSpec> resumableUploadSpec)
public SignalServiceAttachmentPointer(int cdnNumber,
SignalServiceAttachmentRemoteId remoteId,
String contentType,
byte[] key,
Optional<Integer> size,
Optional<byte[]> preview,
int width,
int height,
Optional<byte[]> digest,
Optional<String> fileName,
boolean voiceNote,
boolean borderless,
Optional<String> caption,
Optional<String> blurHash,
long uploadTimestamp)
other stuff :
private long id; // used by v2 attachments, see note
private int keyLength; //TODO: if you're going to do that, probably should have previewLength and digestLength
notes :
"size" appears to be the same as "length" but is int rather than long
"length" represents file size (or stream/attachment size)
"preview" is also known as "thumbnail"
from SignalServiceAttachmentRemoteId.java :
* Represents a signal service attachment identifier. This can be either a CDN key or a long, but
* not both at once. Attachments V2 used a long as an attachment identifier. This lacks sufficient
* entropy to reduce the likelihood of any two uploads going to the same location within a 30-day
* window. Attachments V3 uses an opaque string as an attachment identifier which provides more
* flexibility in the amount of entropy present.
*/
public DbusAttachment(SignalServiceAttachment attachment) {
this.contentType = attachment.getContentType();
if (attachment.isPointer()) {
final var pointer = attachment.asPointer();
this.id = pointer.getRemoteId().toString();
this.fileName = pointer.getFileName().orNull();
if (this.fileName == null) {
this.fileName = "";
}
this.size = pointer.getSize().transform(Integer::longValue).orNull();
if (this.size == null) {
this.size = 0L;
}
this.setKeyLength(pointer.getKey().length);
this.setWidth(pointer.getWidth());
this.setHeight(pointer.getHeight());
this.setVoiceNote(pointer.getVoiceNote());
if (pointer.getCaption().isPresent()) {
this.setCaption(pointer.getCaption().get());
} else {
this.setCaption("");
}
this.setBlurHash("");
} else {
final var stream = attachment.asStream();
this.fileName = stream.getFileName().orNull();
if (this.fileName == null) {
this.fileName = "";
}
this.id = "";
this.size = stream.getLength();
this.setKeyLength(0);
this.setWidth(0);
this.setHeight(0);
this.setVoiceNote(false);
this.setCaption("");
this.setBlurHash("");
}
}
public DbusAttachment(String fileName) {
this.contentType = "application/octet-stream";
try {
final File file = new File(fileName);
this.contentType = Utils.getFileMimeType(file, "application/octet-stream");
this.size = file.length();
} catch (IOException e) {
//no such file, try URL
try {
final URL aURL = new URL(fileName);
this.contentType = aURL.openConnection().getContentType();
this.size = aURL.openConnection().getContentLengthLong();
} catch (IOException f) {
f.printStackTrace();
}
}
this.fileName = fileName;
this.id = "";
this.setKeyLength(0);
this.setWidth(0);
this.setHeight(0);
this.setVoiceNote(false);
this.setCaption("");
this.setBlurHash("");
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public Long getFileSize() {
return size;
}
public void setFileSize(Long size) {
this.size = size;
}
public Integer getKeyLength() {
return keyLength;
}
public void setKeyLength(Integer keyLength) {
this.keyLength = keyLength;
}
public Integer getWidth() {
return width;
}
public void setWidth(Integer width) {
this.width = width;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
public boolean isVoiceNote() {
return voiceNote;
}
public boolean getVoiceNote() {
return voiceNote;
}
public void setVoiceNote(boolean voiceNote) {
this.voiceNote = voiceNote;
}
public String getCaption() {
return caption;
}
public void setCaption(String caption) {
this.caption = caption;
}
public String getBlurHash() {
return blurHash;
}
public void setBlurHash(String blurHash) {
this.blurHash = blurHash;
}
}

View file

@ -150,6 +150,7 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl {
return BaseConfig.PROJECT_VERSION; return BaseConfig.PROJECT_VERSION;
} }
@Override
public List<DBusPath> listAccounts() { public List<DBusPath> listAccounts() {
synchronized (receiveThreads) { synchronized (receiveThreads) {
return receiveThreads.stream() return receiveThreads.stream()

View file

@ -7,7 +7,6 @@ import org.asamk.signal.PlainTextWriter;
import org.asamk.signal.PlainTextWriterImpl; import org.asamk.signal.PlainTextWriterImpl;
import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.commands.exceptions.IOErrorException;
import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.dbus.DbusAttachment;
import org.asamk.signal.manager.AttachmentInvalidException; import org.asamk.signal.manager.AttachmentInvalidException;
import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.NotMasterDeviceException; import org.asamk.signal.manager.NotMasterDeviceException;
@ -112,36 +111,10 @@ public class DbusSignalImpl implements Signal {
return results; return results;
} }
@Override @Override
public long sendMessageWithDBusAttachments(final String message, final List<DbusAttachment> dBusAttachments, final String recipient) { public long sendMessage(final String message, final List<String> attachments, final String recipient) {
var recipients = new ArrayList<String>(1); var recipients = new ArrayList<String>(1);
recipients.add(recipient); recipients.add(recipient);
return sendMessageWithDBusAttachments(message, dBusAttachments, recipients); return sendMessage(message, attachments, recipients);
}
@Override
public long sendMessageWithDBusAttachments(final String message, final List<DbusAttachment> dBusAttachments, final List<String> recipients) {
try {
ArrayList<String> attachmentNames = new ArrayList<>();
for (var dBusAttachment : dBusAttachments) {
attachmentNames.add(dBusAttachment.getFileName());
}
final var results = m.sendMessage(message, attachmentNames, recipients);
checkSendMessageResults(results.first(), results.second());
return results.first();
} catch (InvalidNumberException e) {
throw new Error.InvalidNumber(e.getMessage());
} catch (AttachmentInvalidException e) {
throw new Error.AttachmentInvalid(e.getMessage());
} catch (IOException e) {
throw new Error.Failure(e.getMessage());
}
}
@Override
public long sendMessage(final String message, final List<String> attachmentNames, final String recipient) {
var recipients = new ArrayList<String>(1);
recipients.add(recipient);
return sendMessage(message, attachmentNames, recipients);
} }
private static void checkSendMessageResult(long timestamp, SendMessageResult result) throws DBusExecutionException { private static void checkSendMessageResult(long timestamp, SendMessageResult result) throws DBusExecutionException {
@ -184,9 +157,9 @@ public class DbusSignalImpl implements Signal {
} }
@Override @Override
public long sendMessage(final String message, final List<String> attachmentNames, final List<String> recipients) { public long sendMessage(final String message, final List<String> attachments, final List<String> recipients) {
try { try {
final var results = m.sendMessage(message, attachmentNames, recipients); final var results = m.sendMessage(message, attachments, recipients);
checkSendMessageResults(results.first(), results.second()); checkSendMessageResults(results.first(), results.second());
return results.first(); return results.first();
} catch (InvalidNumberException e) { } catch (InvalidNumberException e) {
@ -271,29 +244,10 @@ public class DbusSignalImpl implements Signal {
@Override @Override
public long sendNoteToSelfMessage( public long sendNoteToSelfMessage(
final String message, final List<String> attachmentNames final String message, final List<String> attachments
) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity { ) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity {
try { try {
final var results = m.sendSelfMessage(message, attachmentNames); final var results = m.sendSelfMessage(message, attachments);
checkSendMessageResult(results.first(), results.second());
return results.first();
} catch (AttachmentInvalidException e) {
throw new Error.AttachmentInvalid(e.getMessage());
} catch (IOException e) {
throw new Error.Failure(e.getMessage());
}
}
@Override
public long sendNoteToSelfMessageWithDBusAttachments(
final String message, final List<DbusAttachment> dBusAttachments
) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity {
try {
ArrayList<String> attachmentNames = new ArrayList<>();
for (var dBusAttachment : dBusAttachments) {
attachmentNames.add(dBusAttachment.getFileName());
}
final var results = m.sendSelfMessage(message, attachmentNames);
checkSendMessageResult(results.first(), results.second()); checkSendMessageResult(results.first(), results.second());
return results.first(); return results.first();
} catch (AttachmentInvalidException e) { } catch (AttachmentInvalidException e) {
@ -316,9 +270,9 @@ public class DbusSignalImpl implements Signal {
} }
@Override @Override
public long sendGroupMessage(final String message, final List<String> attachmentNames, final byte[] groupId) { public long sendGroupMessage(final String message, final List<String> attachments, final byte[] groupId) {
try { try {
var results = m.sendGroupMessage(message, attachmentNames, GroupId.unknownVersion(groupId)); var results = m.sendGroupMessage(message, attachments, GroupId.unknownVersion(groupId));
checkSendMessageResults(results.first(), results.second()); checkSendMessageResults(results.first(), results.second());
return results.first(); return results.first();
} catch (IOException e) { } catch (IOException e) {
@ -330,26 +284,6 @@ public class DbusSignalImpl implements Signal {
} }
} }
@Override
public long sendGroupMessageWithDBusAttachments(final String message, final List<DbusAttachment> dBusAttachments, final byte[] groupId) {
try {
ArrayList<String> attachmentNames = new ArrayList<>();
for (var dBusAttachment : dBusAttachments) {
attachmentNames.add(dBusAttachment.getFileName());
}
var results = m.sendGroupMessage(message, attachmentNames, GroupId.unknownVersion(groupId));
checkSendMessageResults(results.first(), results.second());
return results.first();
} catch (IOException e) {
throw new Error.Failure(e.getMessage());
} catch (GroupNotFoundException | NotAGroupMemberException e) {
throw new Error.GroupNotFound(e.getMessage());
} catch (AttachmentInvalidException e) {
throw new Error.AttachmentInvalid(e.getMessage());
}
}
@Override @Override
public long sendGroupMessageReaction( public long sendGroupMessageReaction(
final String emoji, final String emoji,
@ -397,17 +331,6 @@ public class DbusSignalImpl implements Signal {
} }
} }
@Override
public void setExpirationTimer(final String number, final int expiration) {
try {
m.setExpirationTimer(number, expiration);
} catch (IOException e) {
throw new Error.Failure(e.getMessage());
} catch (InvalidNumberException e) {
throw new Error.InvalidNumber(e.getMessage());
}
}
@Override @Override
public void setContactBlocked(final String number, final boolean blocked) { public void setContactBlocked(final String number, final boolean blocked) {
try { try {

View file

@ -4,8 +4,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.asamk.signal.dbus.DbusAttachment;
class JsonAttachment { class JsonAttachment {
@JsonProperty @JsonProperty
@ -20,33 +18,6 @@ class JsonAttachment {
@JsonProperty @JsonProperty
final Long size; final Long size;
@JsonProperty
Integer keyLength;
@JsonProperty
Integer width;
@JsonProperty
Integer height;
@JsonProperty
boolean voiceNote;
@JsonProperty
String caption;
@JsonProperty
String relay;
@JsonProperty
byte[] preview;
@JsonProperty
String digest;
@JsonProperty
String blurHash;
JsonAttachment(SignalServiceAttachment attachment) { JsonAttachment(SignalServiceAttachment attachment) {
this.contentType = attachment.getContentType(); this.contentType = attachment.getContentType();
@ -55,11 +26,6 @@ class JsonAttachment {
this.id = pointer.getRemoteId().toString(); this.id = pointer.getRemoteId().toString();
this.filename = pointer.getFileName().orNull(); this.filename = pointer.getFileName().orNull();
this.size = pointer.getSize().transform(Integer::longValue).orNull(); this.size = pointer.getSize().transform(Integer::longValue).orNull();
this.keyLength = pointer.getKey().length;
this.width = pointer.getWidth();
this.height = pointer.getHeight();
this.voiceNote = pointer.getVoiceNote();
if (pointer.getCaption().isPresent()) {this.caption = pointer.getCaption().get();}
} else { } else {
final var stream = attachment.asStream(); final var stream = attachment.asStream();
this.id = null; this.id = null;
@ -74,17 +40,4 @@ class JsonAttachment {
this.id = null; this.id = null;
this.size = null; this.size = null;
} }
JsonAttachment(DbusAttachment attachment) {
this.contentType = attachment.getContentType();
this.id = attachment.getId();
this.filename = attachment.getFileName();
this.size = attachment.getFileSize();
this.keyLength = attachment.getKeyLength();
this.width = attachment.getWidth();
this.height = attachment.getHeight();
this.voiceNote = attachment.getVoiceNote();
this.caption = attachment.getCaption();
}
} }

View file

@ -5,7 +5,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import org.asamk.Signal; import org.asamk.Signal;
import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.Manager;
import org.asamk.signal.dbus.DbusAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import java.util.List; import java.util.List;
@ -127,7 +126,6 @@ class JsonDataMessage {
sticker = null; sticker = null;
contacts = null; contacts = null;
attachments = messageReceived.getAttachments().stream().map(JsonAttachment::new).collect(Collectors.toList()); attachments = messageReceived.getAttachments().stream().map(JsonAttachment::new).collect(Collectors.toList());
} }
public JsonDataMessage(Signal.SyncMessageReceived messageReceived) { public JsonDataMessage(Signal.SyncMessageReceived messageReceived) {

View file

@ -7,9 +7,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupId;
import org.asamk.signal.manager.groups.GroupIdFormatException; import org.asamk.signal.manager.groups.GroupIdFormatException;
import org.asamk.signal.dbus.DbusAttachment;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import java.util.Arrays; import java.util.Arrays;