mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15:22 +00:00
Resign ourselves to a less sophisticated contact intersection method.
This commit is contained in:
parent
073b1f69e3
commit
75cca3add1
@ -67,7 +67,7 @@ public class PreKeyUtil {
|
|||||||
|
|
||||||
for (String keyRecordId : keyRecordIds) {
|
for (String keyRecordId : keyRecordIds) {
|
||||||
try {
|
try {
|
||||||
if (Integer.parseInt(keyRecordId) != Medium.MAX_VALUE) {
|
if (!keyRecordId.equals(PreKeyIndex.FILE_NAME) && Integer.parseInt(keyRecordId) != Medium.MAX_VALUE) {
|
||||||
records.add(new PreKeyRecord(context, masterSecret, Integer.parseInt(keyRecordId)));
|
records.add(new PreKeyRecord(context, masterSecret, Integer.parseInt(keyRecordId)));
|
||||||
}
|
}
|
||||||
} catch (InvalidKeyIdException e) {
|
} catch (InvalidKeyIdException e) {
|
||||||
|
@ -0,0 +1,175 @@
|
|||||||
|
package org.whispersystems.textsecure.directory;
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.provider.ContactsContract.CommonDataKinds.Phone;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.whispersystems.textsecure.util.Base64;
|
||||||
|
import org.whispersystems.textsecure.util.PhoneNumberFormatter;
|
||||||
|
import org.whispersystems.textsecure.util.Util;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class Directory {
|
||||||
|
|
||||||
|
private static final String DATABASE_NAME = "whisper_directory.db";
|
||||||
|
private static final int DATABASE_VERSION = 1;
|
||||||
|
|
||||||
|
private static final String TABLE_NAME = "directory";
|
||||||
|
private static final String ID = "_id";
|
||||||
|
private static final String TOKEN = "token";
|
||||||
|
private static final String REGISTERED = "registered";
|
||||||
|
private static final String SUPPORTS_SMS = "supports_sms";
|
||||||
|
private static final String TIMESTAMP = "timestamp";
|
||||||
|
private static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + ID + " INTEGER PRIMARY KEY, " +
|
||||||
|
TOKEN + " TEXT UNIQUE, " + REGISTERED + " INTEGER, " +
|
||||||
|
SUPPORTS_SMS + " INTEGER, " + TIMESTAMP + " INTEGER);";
|
||||||
|
|
||||||
|
private static Directory instance;
|
||||||
|
|
||||||
|
public synchronized static Directory getInstance(Context context) {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new Directory(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final DatabaseHelper databaseHelper;
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
private Directory(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
this.databaseHelper = new DatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsNumbers(List<String> e164numbers) {
|
||||||
|
if (e164numbers == null || e164numbers.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String e164number : e164numbers) {
|
||||||
|
if (!containsNumber(e164number))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsNumber(String e164number) {
|
||||||
|
if (e164number == null || e164number.length() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||||
|
String token = getToken(e164number);
|
||||||
|
Cursor cursor = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
cursor = db.query(TABLE_NAME,
|
||||||
|
new String[] {REGISTERED}, TOKEN + " = ?",
|
||||||
|
new String[] {token}, null, null, null);
|
||||||
|
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
return cursor.getInt(0) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
if (cursor != null)
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActiveTokens(List<String> tokens) {
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||||
|
db.beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
ContentValues clear = new ContentValues();
|
||||||
|
clear.put(REGISTERED, 0);
|
||||||
|
clear.put(TIMESTAMP, timestamp);
|
||||||
|
db.update(TABLE_NAME, clear, null, null);
|
||||||
|
|
||||||
|
|
||||||
|
for (String token : tokens) {
|
||||||
|
Log.w("Directory", "Adding token: " + token);
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(TOKEN, token);
|
||||||
|
values.put(REGISTERED, 1);
|
||||||
|
values.put(TIMESTAMP, timestamp);
|
||||||
|
db.replace(TABLE_NAME, null, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
} finally {
|
||||||
|
db.endTransaction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getPushEligibleContactTokens(String localNumber) {
|
||||||
|
Uri uri = Phone.CONTENT_URI;
|
||||||
|
Set<String> results = new HashSet<String>();
|
||||||
|
Cursor cursor = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
cursor = context.getContentResolver().query(uri, new String[] {Phone.NUMBER}, null, null, null);
|
||||||
|
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
String rawNumber = cursor.getString(0);
|
||||||
|
|
||||||
|
if (rawNumber != null) {
|
||||||
|
String e164Number = PhoneNumberFormatter.formatNumber(rawNumber, localNumber);
|
||||||
|
results.add(getToken(e164Number));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
} finally {
|
||||||
|
if (cursor != null)
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getToken(String e164number) {
|
||||||
|
try {
|
||||||
|
MessageDigest digest = MessageDigest.getInstance("SHA1");
|
||||||
|
byte[] token = Util.trim(digest.digest(e164number.getBytes()), 10);
|
||||||
|
return Base64.encodeBytesWithoutPadding(token);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DatabaseHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
|
public DatabaseHelper(Context context, String name,
|
||||||
|
SQLiteDatabase.CursorFactory factory,
|
||||||
|
int version)
|
||||||
|
{
|
||||||
|
super(context, name, factory, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
db.execSQL(CREATE_TABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package org.whispersystems.textsecure.push;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ContactTokenList {
|
||||||
|
|
||||||
|
private List<String> contacts;
|
||||||
|
|
||||||
|
public ContactTokenList(List<String> contacts) {
|
||||||
|
this.contacts = contacts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContactTokenList() {}
|
||||||
|
|
||||||
|
public List<String> getContacts() {
|
||||||
|
return contacts;
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,6 @@ import com.google.thoughtcrimegson.Gson;
|
|||||||
import org.whispersystems.textsecure.R;
|
import org.whispersystems.textsecure.R;
|
||||||
import org.whispersystems.textsecure.Release;
|
import org.whispersystems.textsecure.Release;
|
||||||
import org.whispersystems.textsecure.crypto.IdentityKey;
|
import org.whispersystems.textsecure.crypto.IdentityKey;
|
||||||
import org.whispersystems.textsecure.directory.DirectoryDescriptor;
|
|
||||||
import org.whispersystems.textsecure.storage.PreKeyRecord;
|
import org.whispersystems.textsecure.storage.PreKeyRecord;
|
||||||
import org.whispersystems.textsecure.util.Base64;
|
import org.whispersystems.textsecure.util.Base64;
|
||||||
import org.whispersystems.textsecure.util.Util;
|
import org.whispersystems.textsecure.util.Util;
|
||||||
@ -33,6 +32,7 @@ import java.security.cert.CertificateException;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class PushServiceSocket {
|
public class PushServiceSocket {
|
||||||
|
|
||||||
@ -169,16 +169,13 @@ public class PushServiceSocket {
|
|||||||
return attachment;
|
return attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<DirectoryDescriptor, File> retrieveDirectory() {
|
public List<String> retrieveDirectory(Set<String> contactTokens) {
|
||||||
try {
|
try {
|
||||||
DirectoryDescriptor directoryDescriptor = new Gson().fromJson(makeRequest(DIRECTORY_PATH, "GET", null),
|
ContactTokenList contactTokenList = new ContactTokenList(new LinkedList(contactTokens));
|
||||||
DirectoryDescriptor.class);
|
String response = makeRequest(DIRECTORY_PATH, "PUT", new Gson().toJson(contactTokenList));
|
||||||
|
ContactTokenList activeTokens = new Gson().fromJson(response, ContactTokenList.class);
|
||||||
|
|
||||||
File directoryData = File.createTempFile("directory", ".dat", context.getFilesDir());
|
return activeTokens.getContacts();
|
||||||
|
|
||||||
downloadExternalFile(directoryDescriptor.getUrl(), directoryData);
|
|
||||||
|
|
||||||
return new Pair<DirectoryDescriptor, File>(directoryDescriptor, directoryData);
|
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
Log.w("PushServiceSocket", ioe);
|
Log.w("PushServiceSocket", ioe);
|
||||||
return null;
|
return null;
|
||||||
|
@ -73,6 +73,13 @@ public class Util {
|
|||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] trim(byte[] input, int length) {
|
||||||
|
byte[] result = new byte[length];
|
||||||
|
System.arraycopy(input, 0, result, 0, result.length);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isEmpty(String value) {
|
public static boolean isEmpty(String value) {
|
||||||
return value == null || value.trim().length() == 0;
|
return value == null || value.trim().length() == 0;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import android.os.Binder;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import com.google.android.gcm.GCMRegistrar;
|
import com.google.android.gcm.GCMRegistrar;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
@ -20,15 +19,14 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
|||||||
import org.whispersystems.textsecure.crypto.IdentityKey;
|
import org.whispersystems.textsecure.crypto.IdentityKey;
|
||||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||||
import org.whispersystems.textsecure.crypto.PreKeyUtil;
|
import org.whispersystems.textsecure.crypto.PreKeyUtil;
|
||||||
import org.whispersystems.textsecure.directory.DirectoryDescriptor;
|
import org.whispersystems.textsecure.directory.Directory;
|
||||||
import org.whispersystems.textsecure.directory.NumberFilter;
|
|
||||||
import org.whispersystems.textsecure.push.PushServiceSocket;
|
import org.whispersystems.textsecure.push.PushServiceSocket;
|
||||||
import org.whispersystems.textsecure.storage.PreKeyRecord;
|
import org.whispersystems.textsecure.storage.PreKeyRecord;
|
||||||
import org.whispersystems.textsecure.util.Util;
|
import org.whispersystems.textsecure.util.Util;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
@ -282,12 +280,14 @@ public class RegistrationService extends Service {
|
|||||||
setState(new RegistrationState(RegistrationState.STATE_GCM_REGISTERING, number));
|
setState(new RegistrationState(RegistrationState.STATE_GCM_REGISTERING, number));
|
||||||
GCMRegistrar.register(this, GcmIntentService.GCM_SENDER_ID);
|
GCMRegistrar.register(this, GcmIntentService.GCM_SENDER_ID);
|
||||||
String gcmRegistrationId = waitForGcmRegistrationId();
|
String gcmRegistrationId = waitForGcmRegistrationId();
|
||||||
|
|
||||||
socket.registerGcmId(gcmRegistrationId);
|
socket.registerGcmId(gcmRegistrationId);
|
||||||
Pair<DirectoryDescriptor, File> directory = socket.retrieveDirectory();
|
|
||||||
|
|
||||||
if (directory != null) {
|
Set<String> contactTokens = Directory.getInstance(this).getPushEligibleContactTokens(number);
|
||||||
NumberFilter.getInstance(this).update(directory.first, directory.second);
|
List<String> activeTokens = socket.retrieveDirectory(contactTokens);
|
||||||
|
|
||||||
|
if (activeTokens != null) {
|
||||||
|
Directory.getInstance(this).setActiveTokens(activeTokens);
|
||||||
|
// NumberFilter.getInstance(this).update(directory.first, directory.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +20,12 @@ import android.content.Context;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
|
||||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.textsecure.directory.NumberFilter;
|
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||||
|
import org.whispersystems.textsecure.directory.Directory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -57,7 +57,7 @@ public class UniversalTransport {
|
|||||||
Recipient recipient = message.getIndividualRecipient();
|
Recipient recipient = message.getIndividualRecipient();
|
||||||
String number = Util.canonicalizeNumber(context, recipient.getNumber());
|
String number = Util.canonicalizeNumber(context, recipient.getNumber());
|
||||||
|
|
||||||
if (NumberFilter.getInstance(context).containsNumber(number)) {
|
if (Directory.getInstance(context).containsNumber(number)) {
|
||||||
try {
|
try {
|
||||||
Log.w("UniversalTransport", "Delivering with GCM...");
|
Log.w("UniversalTransport", "Delivering with GCM...");
|
||||||
pushTransport.deliver(message);
|
pushTransport.deliver(message);
|
||||||
@ -78,7 +78,7 @@ public class UniversalTransport {
|
|||||||
|
|
||||||
List<String> destinations = getMediaDestinations(mediaMessage);
|
List<String> destinations = getMediaDestinations(mediaMessage);
|
||||||
|
|
||||||
if (NumberFilter.getInstance(context).containsNumbers(destinations)) {
|
if (Directory.getInstance(context).containsNumbers(destinations)) {
|
||||||
try {
|
try {
|
||||||
Log.w("UniversalTransport", "Delivering media message with GCM...");
|
Log.w("UniversalTransport", "Delivering media message with GCM...");
|
||||||
pushTransport.deliver(mediaMessage, destinations);
|
pushTransport.deliver(mediaMessage, destinations);
|
||||||
|
Loading…
Reference in New Issue
Block a user