Skip to content

Commit

Permalink
Fill in group creation actions
Browse files Browse the repository at this point in the history
  • Loading branch information
moxie0 committed Feb 14, 2014
1 parent 41aa53d commit 7c46f3c
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 16 deletions.
83 changes: 77 additions & 6 deletions src/org/thoughtcrime/securesms/GroupCreateActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
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;
Expand All @@ -19,31 +19,43 @@
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 {
Expand Down Expand Up @@ -237,7 +249,15 @@ protected Void doInBackground(Void... voids) {
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;
}

Expand Down Expand Up @@ -334,11 +354,62 @@ public void onClick(View v) {
}
}

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 long handleCreateMmsGroup(Set<Recipient> members) {
Recipients recipients = new Recipients(new LinkedList<Recipient>(members));
return DatabaseFactory.getThreadDatabase(this)
.getThreadIdFor(recipients,
ThreadDatabase.DistributionTypes.CONVERSATION);
}

private void handleCreateMmsGroup(Set<Recipient> members) {
//todo
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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ public void processKeyExchangeMessage(PreKeyEntity message, long threadId)
DatabaseFactory.getIdentityDatabase(context)
.saveIdentity(masterSecret, recipientDevice.getRecipientId(), message.getIdentityKey());

broadcastSecurityUpdateEvent(context, threadId);
if (threadId != -1) {
broadcastSecurityUpdateEvent(context, threadId);
}
}

@Override
Expand Down
19 changes: 17 additions & 2 deletions src/org/thoughtcrime/securesms/database/GroupDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
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;

Expand Down Expand Up @@ -122,14 +124,17 @@ public void update(byte[] groupId, String source, String title, AttachmentPointe
}

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);

Expand Down Expand Up @@ -177,6 +182,16 @@ private List<String> getCurrentMembers(byte[] id) {
}
}

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 {

Expand Down
57 changes: 57 additions & 0 deletions src/org/thoughtcrime/securesms/push/GroupActionRecord.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
60 changes: 53 additions & 7 deletions src/org/thoughtcrime/securesms/transport/PushTransport.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,45 @@ public void deliver(SendReq message, long threadId) throws IOException {
}
}

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
{
Expand Down Expand Up @@ -151,19 +190,26 @@ private List<PushAttachmentPointer> getPushAttachmentPointers(PushServiceSocket
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)
Expand Down

0 comments on commit 7c46f3c

Please sign in to comment.