mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-24 00:37:47 +00:00
Fill in group creation actions
This commit is contained in:
parent
41aa53dd66
commit
7c46f3cbf8
@ -6,10 +6,10 @@ import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
@ -19,31 +19,43 @@ import android.widget.TextView;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.thoughtcrime.securesms.components.PushRecipientsPanel;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.transport.PushTransport;
|
||||
import org.thoughtcrime.securesms.util.ActionBarUtil;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.SelectedRecipientsAdapter;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
import org.whispersystems.textsecure.directory.Directory;
|
||||
import org.whispersystems.textsecure.directory.NotInDirectoryException;
|
||||
import org.whispersystems.textsecure.push.PushAttachmentPointer;
|
||||
import org.whispersystems.textsecure.util.InvalidNumberException;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
import static org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent.AttachmentPointer;
|
||||
import static org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent.GroupContext;
|
||||
|
||||
|
||||
public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActivity {
|
||||
@ -237,7 +249,15 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActiv
|
||||
avatarBmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
|
||||
byteArray = stream.toByteArray();
|
||||
}
|
||||
handleCreatePushGroup(groupName.getText().toString(), byteArray, selectedContacts);
|
||||
try {
|
||||
handleCreatePushGroup(groupName.getText().toString(), byteArray, selectedContacts);
|
||||
} catch (IOException e) {
|
||||
// TODO Jake's gonna fill this in.
|
||||
Log.w("GroupCreateActivity", e);
|
||||
} catch (InvalidNumberException e) {
|
||||
// TODO jake's gonna fill this in.
|
||||
Log.w("GroupCreateActivity", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -334,11 +354,62 @@ public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActiv
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCreatePushGroup(String groupName, byte[] avatar, Set<Recipient> members) {
|
||||
//todo
|
||||
private Pair<Long, List<Recipient>> handleCreatePushGroup(String groupName,
|
||||
byte[] avatar,
|
||||
Set<Recipient> members)
|
||||
throws IOException, InvalidNumberException
|
||||
{
|
||||
List<String> memberE164Numbers = getE164Numbers(members);
|
||||
PushTransport transport = new PushTransport(this, masterSecret);
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(this);
|
||||
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(this);
|
||||
byte[] groupId = groupDatabase.allocateGroupId();
|
||||
AttachmentPointer avatarPointer = null;
|
||||
|
||||
GroupContext.Builder builder = GroupContext.newBuilder()
|
||||
.setId(ByteString.copyFrom(groupId))
|
||||
.setType(GroupContext.Type.CREATE)
|
||||
.setName(groupName)
|
||||
.addAllMembers(memberE164Numbers);
|
||||
|
||||
if (avatar != null) {
|
||||
PushAttachmentPointer pointer = transport.createAttachment("image/png", avatar);
|
||||
avatarPointer = AttachmentPointer.newBuilder()
|
||||
.setKey(ByteString.copyFrom(pointer.getKey()))
|
||||
.setContentType(pointer.getContentType())
|
||||
.setId(pointer.getId()).build();
|
||||
builder.setAvatar(avatarPointer);
|
||||
}
|
||||
|
||||
List<Recipient> failures = transport.deliver(new LinkedList<Recipient>(members), builder.build());
|
||||
groupDatabase.create(groupId, TextSecurePreferences.getLocalNumber(this), groupName,
|
||||
memberE164Numbers, avatarPointer, null);
|
||||
|
||||
if (avatar != null) {
|
||||
groupDatabase.updateAvatar(groupId, avatar);
|
||||
}
|
||||
|
||||
long threadId = threadDatabase.getThreadIdForGroup(GroupUtil.getEncodedId(groupId));
|
||||
|
||||
return new Pair<Long, List<Recipient>>(threadId, failures);
|
||||
}
|
||||
|
||||
private void handleCreateMmsGroup(Set<Recipient> members) {
|
||||
//todo
|
||||
private long handleCreateMmsGroup(Set<Recipient> members) {
|
||||
Recipients recipients = new Recipients(new LinkedList<Recipient>(members));
|
||||
return DatabaseFactory.getThreadDatabase(this)
|
||||
.getThreadIdFor(recipients,
|
||||
ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||
}
|
||||
|
||||
private List<String> getE164Numbers(Set<Recipient> recipients)
|
||||
throws InvalidNumberException
|
||||
{
|
||||
List<String> results = new LinkedList<String>();
|
||||
|
||||
for (Recipient recipient : recipients) {
|
||||
results.add(Util.canonicalizeNumber(this, recipient.getNumber()));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +135,9 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
||||
DatabaseFactory.getIdentityDatabase(context)
|
||||
.saveIdentity(masterSecret, recipientDevice.getRecipientId(), message.getIdentityKey());
|
||||
|
||||
broadcastSecurityUpdateEvent(context, threadId);
|
||||
if (threadId != -1) {
|
||||
broadcastSecurityUpdateEvent(context, threadId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -18,6 +18,8 @@ import org.whispersystems.textsecure.util.Hex;
|
||||
import org.whispersystems.textsecure.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@ -122,14 +124,17 @@ public class GroupDatabase extends Database {
|
||||
}
|
||||
|
||||
public void updateAvatar(byte[] groupId, Bitmap avatar) {
|
||||
updateAvatar(groupId, BitmapUtil.toByteArray(avatar));
|
||||
}
|
||||
|
||||
public void updateAvatar(byte[] groupId, byte[] avatar) {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(AVATAR, BitmapUtil.toByteArray(avatar));
|
||||
contentValues.put(AVATAR, avatar);
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
||||
new String[] {GroupUtil.getEncodedId(groupId)});
|
||||
}
|
||||
|
||||
|
||||
public void add(byte[] id, String source, List<String> members) {
|
||||
List<String> currentMembers = getCurrentMembers(id);
|
||||
|
||||
@ -177,6 +182,16 @@ public class GroupDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] allocateGroupId() {
|
||||
try {
|
||||
byte[] groupId = new byte[16];
|
||||
SecureRandom.getInstance("SHA1PRNG").nextBytes(groupId);
|
||||
return groupId;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Reader {
|
||||
|
||||
|
57
src/org/thoughtcrime/securesms/push/GroupActionRecord.java
Normal file
57
src/org/thoughtcrime/securesms/push/GroupActionRecord.java
Normal file
@ -0,0 +1,57 @@
|
||||
package org.thoughtcrime.securesms.push;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class GroupActionRecord {
|
||||
|
||||
private static final int CREATE_GROUP_TYPE = 1;
|
||||
private static final int ADD_USERS_TYPE = 2;
|
||||
private static final int LEAVE_GROUP_TYPE = 3;
|
||||
|
||||
private final int type;
|
||||
private final Set<Recipient> recipients;
|
||||
private final byte[] groupId;
|
||||
private final String groupName;
|
||||
private final byte[] avatar;
|
||||
|
||||
public GroupActionRecord(int type, byte[] groupId, String groupName,
|
||||
byte[] avatar, Set<Recipient> recipients)
|
||||
{
|
||||
this.type = type;
|
||||
this.groupId = groupId;
|
||||
this.groupName = groupName;
|
||||
this.avatar = avatar;
|
||||
this.recipients = recipients;
|
||||
}
|
||||
|
||||
public boolean isCreateAction() {
|
||||
return type== CREATE_GROUP_TYPE;
|
||||
}
|
||||
|
||||
public boolean isAddUsersAction() {
|
||||
return type == ADD_USERS_TYPE;
|
||||
}
|
||||
|
||||
public boolean isLeaveAction() {
|
||||
return type == LEAVE_GROUP_TYPE;
|
||||
}
|
||||
|
||||
|
||||
public Set<Recipient> getRecipients() {
|
||||
return recipients;
|
||||
}
|
||||
|
||||
public byte[] getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public byte[] getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
}
|
@ -123,6 +123,45 @@ public class PushTransport extends BaseTransport {
|
||||
}
|
||||
}
|
||||
|
||||
public List<Recipient> deliver(List<Recipient> recipients,
|
||||
PushMessageContent.GroupContext groupAction)
|
||||
throws IOException
|
||||
{
|
||||
PushServiceSocket socket = PushServiceSocketFactory.create(context);
|
||||
byte[] plaintext = PushMessageContent.newBuilder()
|
||||
.setGroup(groupAction)
|
||||
.build().toByteArray();
|
||||
List<Recipient> failures = new LinkedList<Recipient>();
|
||||
|
||||
for (Recipient recipient : recipients) {
|
||||
try {
|
||||
deliver(socket, recipient, -1, plaintext);
|
||||
} catch (UnregisteredUserException e) {
|
||||
Log.w("PushTransport", e);
|
||||
failures.add(recipient);
|
||||
} catch (InvalidNumberException e) {
|
||||
Log.w("PushTransport", e);
|
||||
failures.add(recipient);
|
||||
} catch (IOException e) {
|
||||
Log.w("PushTransport", e);
|
||||
failures.add(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
if (failures.size() == recipients.size()) {
|
||||
throw new IOException("Total failure.");
|
||||
}
|
||||
|
||||
return failures;
|
||||
}
|
||||
|
||||
public PushAttachmentPointer createAttachment(String contentType, byte[] data)
|
||||
throws IOException
|
||||
{
|
||||
PushServiceSocket socket = PushServiceSocketFactory.create(context);
|
||||
return getPushAttachmentPointer(socket, contentType, data);
|
||||
}
|
||||
|
||||
private void deliver(PushServiceSocket socket, Recipient recipient, long threadId, byte[] plaintext)
|
||||
throws IOException, InvalidNumberException
|
||||
{
|
||||
@ -151,19 +190,26 @@ public class PushTransport extends BaseTransport {
|
||||
ContentType.isAudioType(contentType) ||
|
||||
ContentType.isVideoType(contentType))
|
||||
{
|
||||
AttachmentCipher cipher = new AttachmentCipher();
|
||||
byte[] key = cipher.getCombinedKeyMaterial();
|
||||
byte[] ciphertextAttachment = cipher.encrypt(body.getPart(i).getData());
|
||||
PushAttachmentData attachmentData = new PushAttachmentData(contentType, ciphertextAttachment);
|
||||
long attachmentId = socket.sendAttachment(attachmentData);
|
||||
|
||||
attachments.add(new PushAttachmentPointer(contentType, attachmentId, key));
|
||||
attachments.add(getPushAttachmentPointer(socket, contentType, body.getPart(i).getData()));
|
||||
}
|
||||
}
|
||||
|
||||
return attachments;
|
||||
}
|
||||
|
||||
private PushAttachmentPointer getPushAttachmentPointer(PushServiceSocket socket,
|
||||
String contentType, byte[] data)
|
||||
throws IOException
|
||||
{
|
||||
AttachmentCipher cipher = new AttachmentCipher();
|
||||
byte[] key = cipher.getCombinedKeyMaterial();
|
||||
byte[] ciphertextAttachment = cipher.encrypt(data);
|
||||
PushAttachmentData attachmentData = new PushAttachmentData(contentType, ciphertextAttachment);
|
||||
long attachmentId = socket.sendAttachment(attachmentData);
|
||||
|
||||
return new PushAttachmentPointer(contentType, attachmentId, key);
|
||||
}
|
||||
|
||||
private void handleMismatchedDevices(PushServiceSocket socket, long threadId,
|
||||
Recipient recipient,
|
||||
MismatchedDevices mismatchedDevices)
|
||||
|
Loading…
x
Reference in New Issue
Block a user