Signal-Android/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsInputStream.java

98 lines
4.4 KiB
Java

/*
* Copyright (C) 2014-2018 Open Whisper Systems
*
* Licensed according to the LICENSE file in this repository.
*/
package org.whispersystems.signalservice.api.messages.multidevice;
import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.InvalidMessageException;
import org.whispersystems.libsignal.logging.Log;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.util.UuidUtil;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
import org.whispersystems.signalservice.internal.util.Util;
import java.io.IOException;
import java.io.InputStream;
public class DeviceContactsInputStream extends ChunkedInputStream {
private static final String TAG = DeviceContactsInputStream.class.getSimpleName();
public DeviceContactsInputStream(InputStream in) {
super(in);
}
public DeviceContact read() throws IOException {
long detailsLength = readRawVarint32();
byte[] detailsSerialized = new byte[(int)detailsLength];
Util.readFully(in, detailsSerialized);
SignalServiceProtos.ContactDetails details = SignalServiceProtos.ContactDetails.parseFrom(detailsSerialized);
if (!SignalServiceAddress.isValidAddress(details.getUuid(), details.getNumber())) {
throw new IOException("Missing contact address!");
}
SignalServiceAddress address = new SignalServiceAddress(UuidUtil.parseOrNull(details.getUuid()), details.getNumber());
Optional<String> name = Optional.fromNullable(details.getName());
Optional<SignalServiceAttachmentStream> avatar = Optional.absent();
Optional<String> color = details.hasColor() ? Optional.of(details.getColor()) : Optional.<String>absent();
Optional<VerifiedMessage> verified = Optional.absent();
Optional<byte[]> profileKey = Optional.absent();
boolean blocked = false;
Optional<Integer> expireTimer = Optional.absent();
if (details.hasAvatar()) {
long avatarLength = details.getAvatar().getLength();
InputStream avatarStream = new LimitedInputStream(in, avatarLength);
String avatarContentType = details.getAvatar().getContentType();
avatar = Optional.of(new SignalServiceAttachmentStream(avatarStream, avatarContentType, avatarLength, Optional.<String>absent(), false, null));
}
if (details.hasVerified()) {
try {
if (!SignalServiceAddress.isValidAddress(details.getVerified().getDestinationUuid(), details.getVerified().getDestinationE164())) {
throw new InvalidMessageException("Missing Verified address!");
}
IdentityKey identityKey = new IdentityKey(details.getVerified().getIdentityKey().toByteArray(), 0);
SignalServiceAddress destination = new SignalServiceAddress(UuidUtil.parseOrNull(details.getVerified().getDestinationUuid()),
details.getVerified().getDestinationE164());
VerifiedMessage.VerifiedState state;
switch (details.getVerified().getState()) {
case VERIFIED: state = VerifiedMessage.VerifiedState.VERIFIED; break;
case UNVERIFIED:state = VerifiedMessage.VerifiedState.UNVERIFIED; break;
case DEFAULT: state = VerifiedMessage.VerifiedState.DEFAULT; break;
default: throw new InvalidMessageException("Unknown state: " + details.getVerified().getState());
}
verified = Optional.of(new VerifiedMessage(destination, identityKey, state, System.currentTimeMillis()));
} catch (InvalidKeyException | InvalidMessageException e) {
Log.w(TAG, e);
verified = Optional.absent();
}
}
if (details.hasProfileKey()) {
profileKey = Optional.fromNullable(details.getProfileKey().toByteArray());
}
if (details.hasExpireTimer() && details.getExpireTimer() > 0) {
expireTimer = Optional.of(details.getExpireTimer());
}
blocked = details.getBlocked();
return new DeviceContact(address, name, avatar, color, verified, profileKey, blocked, expireTimer);
}
}