2013-07-10 16:22:58 -07:00
|
|
|
package org.whispersystems.textsecure.push;
|
2013-03-25 21:26:03 -07:00
|
|
|
|
|
|
|
import android.content.Context;
|
2013-03-31 19:16:06 -07:00
|
|
|
import android.util.Log;
|
2013-07-17 15:13:00 -07:00
|
|
|
import android.util.Pair;
|
2013-03-25 21:26:03 -07:00
|
|
|
|
|
|
|
import com.google.thoughtcrimegson.Gson;
|
2013-10-18 22:45:27 -07:00
|
|
|
|
2013-07-10 16:33:14 -07:00
|
|
|
import org.whispersystems.textsecure.R;
|
2013-07-10 16:22:58 -07:00
|
|
|
import org.whispersystems.textsecure.Release;
|
2013-08-17 19:06:04 -07:00
|
|
|
import org.whispersystems.textsecure.crypto.IdentityKey;
|
|
|
|
import org.whispersystems.textsecure.storage.PreKeyRecord;
|
|
|
|
import org.whispersystems.textsecure.util.Base64;
|
2013-07-09 19:48:33 -07:00
|
|
|
import org.whispersystems.textsecure.util.Util;
|
2013-03-25 21:26:03 -07:00
|
|
|
|
2013-03-31 19:16:06 -07:00
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileOutputStream;
|
2013-03-25 21:26:03 -07:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.OutputStream;
|
|
|
|
import java.io.UnsupportedEncodingException;
|
2013-07-08 16:29:28 -07:00
|
|
|
import java.net.HttpURLConnection;
|
2013-03-25 21:26:03 -07:00
|
|
|
import java.net.MalformedURLException;
|
|
|
|
import java.net.URL;
|
|
|
|
import java.security.KeyManagementException;
|
|
|
|
import java.security.KeyStore;
|
|
|
|
import java.security.KeyStoreException;
|
|
|
|
import java.security.NoSuchAlgorithmException;
|
|
|
|
import java.security.cert.CertificateException;
|
2013-08-29 17:01:30 -07:00
|
|
|
import java.util.Iterator;
|
2013-07-17 15:13:00 -07:00
|
|
|
import java.util.LinkedList;
|
|
|
|
import java.util.List;
|
2013-09-30 13:24:42 -07:00
|
|
|
import java.util.Set;
|
2013-03-25 21:26:03 -07:00
|
|
|
|
2013-10-18 22:45:27 -07:00
|
|
|
import javax.net.ssl.HttpsURLConnection;
|
|
|
|
import javax.net.ssl.SSLContext;
|
|
|
|
import javax.net.ssl.TrustManagerFactory;
|
|
|
|
|
2013-07-08 16:29:28 -07:00
|
|
|
public class PushServiceSocket {
|
2013-03-25 21:26:03 -07:00
|
|
|
|
2013-10-12 09:46:20 -07:00
|
|
|
private static final String CREATE_ACCOUNT_SMS_PATH = "/v1/accounts/sms/code/%s";
|
|
|
|
private static final String CREATE_ACCOUNT_VOICE_PATH = "/v1/accounts/voice/code/%s";
|
2013-07-08 16:29:28 -07:00
|
|
|
private static final String VERIFY_ACCOUNT_PATH = "/v1/accounts/code/%s";
|
|
|
|
private static final String REGISTER_GCM_PATH = "/v1/accounts/gcm/";
|
2013-08-18 14:35:23 -07:00
|
|
|
private static final String PREKEY_PATH = "/v1/keys/%s";
|
2013-07-08 16:29:28 -07:00
|
|
|
|
2013-10-01 16:26:04 -07:00
|
|
|
private static final String DIRECTORY_TOKENS_PATH = "/v1/directory/tokens";
|
|
|
|
private static final String DIRECTORY_VERIFY_PATH = "/v1/directory/%s";
|
2013-07-08 16:29:28 -07:00
|
|
|
private static final String MESSAGE_PATH = "/v1/messages/";
|
2013-07-17 15:13:00 -07:00
|
|
|
private static final String ATTACHMENT_PATH = "/v1/attachments/%s";
|
2013-03-25 21:26:03 -07:00
|
|
|
|
2013-07-18 17:42:45 -07:00
|
|
|
private final Context context;
|
2013-03-25 21:26:03 -07:00
|
|
|
private final String localNumber;
|
|
|
|
private final String password;
|
|
|
|
private final TrustManagerFactory trustManagerFactory;
|
|
|
|
|
2013-07-08 16:29:28 -07:00
|
|
|
public PushServiceSocket(Context context, String localNumber, String password) {
|
2013-07-18 17:42:45 -07:00
|
|
|
this.context = context.getApplicationContext();
|
2013-03-25 21:26:03 -07:00
|
|
|
this.localNumber = localNumber;
|
|
|
|
this.password = password;
|
|
|
|
this.trustManagerFactory = initializeTrustManagerFactory(context);
|
|
|
|
}
|
|
|
|
|
2013-08-17 19:06:04 -07:00
|
|
|
public void createAccount(boolean voice) throws IOException {
|
2013-07-08 16:29:28 -07:00
|
|
|
String path = voice ? CREATE_ACCOUNT_VOICE_PATH : CREATE_ACCOUNT_SMS_PATH;
|
2013-10-12 09:46:20 -07:00
|
|
|
makeRequest(String.format(path, localNumber), "GET", null);
|
2013-03-25 21:26:03 -07:00
|
|
|
}
|
|
|
|
|
2013-08-28 15:35:30 -07:00
|
|
|
public void verifyAccount(String verificationCode, String signalingKey) throws IOException {
|
|
|
|
SignalingKey signalingKeyEntity = new SignalingKey(signalingKey);
|
|
|
|
makeRequest(String.format(VERIFY_ACCOUNT_PATH, verificationCode), "PUT", new Gson().toJson(signalingKeyEntity));
|
2013-03-25 21:26:03 -07:00
|
|
|
}
|
|
|
|
|
2013-08-17 19:06:04 -07:00
|
|
|
public void registerGcmId(String gcmRegistrationId) throws IOException {
|
2013-03-25 21:26:03 -07:00
|
|
|
GcmRegistrationId registration = new GcmRegistrationId(gcmRegistrationId);
|
2013-07-08 16:29:28 -07:00
|
|
|
makeRequest(REGISTER_GCM_PATH, "PUT", new Gson().toJson(registration));
|
2013-03-25 21:26:03 -07:00
|
|
|
}
|
|
|
|
|
2013-07-18 17:42:45 -07:00
|
|
|
public void unregisterGcmId() throws IOException {
|
2013-07-11 14:58:40 -07:00
|
|
|
makeRequest(REGISTER_GCM_PATH, "DELETE", null);
|
2013-03-31 19:16:06 -07:00
|
|
|
}
|
|
|
|
|
2013-10-18 22:45:27 -07:00
|
|
|
public void sendMessage(String relay, String recipient, byte[] body, int type)
|
2013-07-18 17:42:45 -07:00
|
|
|
throws IOException
|
2013-07-08 16:29:28 -07:00
|
|
|
{
|
2013-10-18 22:45:27 -07:00
|
|
|
OutgoingPushMessage message = new OutgoingPushMessage(relay, recipient, body, type);
|
2013-08-29 17:01:30 -07:00
|
|
|
sendMessage(new OutgoingPushMessageList(message));
|
2013-07-17 15:13:00 -07:00
|
|
|
}
|
|
|
|
|
2013-10-18 22:45:27 -07:00
|
|
|
public void sendMessage(List<String> relays, List<String> recipients,
|
|
|
|
List<byte[]> bodies, List<Integer> types)
|
2013-07-18 17:42:45 -07:00
|
|
|
throws IOException
|
2013-07-17 15:13:00 -07:00
|
|
|
{
|
2013-08-29 17:01:30 -07:00
|
|
|
List<OutgoingPushMessage> messages = new LinkedList<OutgoingPushMessage>();
|
2013-07-17 15:13:00 -07:00
|
|
|
|
2013-10-18 22:45:27 -07:00
|
|
|
Iterator<String> relaysIterator = relays.iterator();
|
2013-09-08 18:19:05 -07:00
|
|
|
Iterator<String> recipientsIterator = recipients.iterator();
|
|
|
|
Iterator<byte[]> bodiesIterator = bodies.iterator();
|
|
|
|
Iterator<Integer> typesIterator = types.iterator();
|
2013-08-29 17:01:30 -07:00
|
|
|
|
|
|
|
while (recipientsIterator.hasNext()) {
|
2013-10-18 22:45:27 -07:00
|
|
|
String relay = relaysIterator.next();
|
2013-09-08 18:19:05 -07:00
|
|
|
String recipient = recipientsIterator.next();
|
|
|
|
byte[] body = bodiesIterator.next();
|
|
|
|
int type = typesIterator.next();
|
2013-08-29 17:01:30 -07:00
|
|
|
|
2013-10-18 22:45:27 -07:00
|
|
|
messages.add(new OutgoingPushMessage(relay, recipient, body, type));
|
2013-08-29 17:01:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
sendMessage(new OutgoingPushMessageList(messages));
|
2013-07-17 15:13:00 -07:00
|
|
|
}
|
|
|
|
|
2013-08-29 17:01:30 -07:00
|
|
|
private void sendMessage(OutgoingPushMessageList messages) throws IOException {
|
|
|
|
String responseText = makeRequest(MESSAGE_PATH, "POST", new Gson().toJson(messages));
|
2013-07-18 17:42:45 -07:00
|
|
|
PushMessageResponse response = new Gson().fromJson(responseText, PushMessageResponse.class);
|
2013-03-31 19:16:06 -07:00
|
|
|
|
|
|
|
if (response.getFailure().size() != 0)
|
|
|
|
throw new IOException("Got send failure: " + response.getFailure().get(0));
|
|
|
|
}
|
|
|
|
|
2013-08-28 15:35:30 -07:00
|
|
|
public void registerPreKeys(IdentityKey identityKey,
|
|
|
|
PreKeyRecord lastResortKey,
|
|
|
|
List<PreKeyRecord> records)
|
2013-08-17 19:06:04 -07:00
|
|
|
throws IOException
|
|
|
|
{
|
2013-08-18 14:35:23 -07:00
|
|
|
List<PreKeyEntity> entities = new LinkedList<PreKeyEntity>();
|
2013-08-17 19:06:04 -07:00
|
|
|
|
|
|
|
for (PreKeyRecord record : records) {
|
2013-08-18 14:35:23 -07:00
|
|
|
PreKeyEntity entity = new PreKeyEntity(record.getId(),
|
|
|
|
record.getKeyPair().getPublicKey(),
|
|
|
|
identityKey);
|
|
|
|
entities.add(entity);
|
2013-08-17 19:06:04 -07:00
|
|
|
}
|
|
|
|
|
2013-08-28 15:35:30 -07:00
|
|
|
PreKeyEntity lastResortEntity = new PreKeyEntity(lastResortKey.getId(),
|
|
|
|
lastResortKey.getKeyPair().getPublicKey(),
|
|
|
|
identityKey);
|
|
|
|
|
|
|
|
makeRequest(String.format(PREKEY_PATH, ""), "PUT", PreKeyList.toJson(new PreKeyList(lastResortEntity, entities)));
|
2013-08-15 08:25:30 -07:00
|
|
|
}
|
|
|
|
|
2013-10-19 10:53:50 -07:00
|
|
|
public PreKeyEntity getPreKey(String relay, String number) throws IOException {
|
2013-10-18 22:45:27 -07:00
|
|
|
String path = String.format(PREKEY_PATH, number);
|
|
|
|
|
|
|
|
if (relay != null) {
|
|
|
|
path = path + "?relay=" + relay;
|
|
|
|
}
|
|
|
|
|
|
|
|
String responseText = makeRequest(path, "GET", null);
|
2013-08-18 14:35:23 -07:00
|
|
|
Log.w("PushServiceSocket", "Got prekey: " + responseText);
|
|
|
|
return PreKeyEntity.fromJson(responseText);
|
|
|
|
}
|
2013-08-15 08:25:30 -07:00
|
|
|
|
2013-09-08 18:19:05 -07:00
|
|
|
public long sendAttachment(PushAttachmentData attachment) throws IOException {
|
2013-07-17 15:13:00 -07:00
|
|
|
Pair<String, String> response = makeRequestForResponseHeader(String.format(ATTACHMENT_PATH, ""),
|
|
|
|
"GET", null, "Content-Location");
|
|
|
|
|
|
|
|
String contentLocation = response.first;
|
|
|
|
Log.w("PushServiceSocket", "Got attachment content location: " + contentLocation);
|
|
|
|
|
|
|
|
if (contentLocation == null) {
|
|
|
|
throw new IOException("Server failed to allocate an attachment key!");
|
|
|
|
}
|
|
|
|
|
|
|
|
uploadExternalFile("PUT", contentLocation, attachment.getData());
|
|
|
|
|
2013-07-18 17:42:45 -07:00
|
|
|
return new Gson().fromJson(response.second, AttachmentKey.class).getId();
|
|
|
|
}
|
|
|
|
|
2013-09-08 18:19:05 -07:00
|
|
|
public File retrieveAttachment(long attachmentId) throws IOException {
|
|
|
|
Pair<String, String> response = makeRequestForResponseHeader(String.format(ATTACHMENT_PATH, String.valueOf(attachmentId)),
|
|
|
|
"GET", null, "Content-Location");
|
2013-07-18 17:42:45 -07:00
|
|
|
|
2013-09-08 18:19:05 -07:00
|
|
|
Log.w("PushServiceSocket", "Attachment: " + attachmentId + " is at: " + response.first);
|
2013-07-18 17:42:45 -07:00
|
|
|
|
2013-09-08 18:19:05 -07:00
|
|
|
File attachment = File.createTempFile("attachment", ".tmp", context.getFilesDir());
|
|
|
|
attachment.deleteOnExit();
|
2013-07-18 17:42:45 -07:00
|
|
|
|
2013-09-08 18:19:05 -07:00
|
|
|
downloadExternalFile(response.first, attachment);
|
2013-07-18 17:42:45 -07:00
|
|
|
|
2013-09-08 18:19:05 -07:00
|
|
|
return attachment;
|
2013-07-17 15:13:00 -07:00
|
|
|
}
|
|
|
|
|
2013-10-18 22:45:27 -07:00
|
|
|
public List<ContactTokenDetails> retrieveDirectory(Set<String> contactTokens) {
|
2013-03-25 21:26:03 -07:00
|
|
|
try {
|
2013-10-18 22:45:27 -07:00
|
|
|
ContactTokenList contactTokenList = new ContactTokenList(new LinkedList(contactTokens));
|
|
|
|
String response = makeRequest(DIRECTORY_TOKENS_PATH, "PUT", new Gson().toJson(contactTokenList));
|
|
|
|
ContactTokenDetailsList activeTokens = new Gson().fromJson(response, ContactTokenDetailsList.class);
|
2013-03-25 21:26:03 -07:00
|
|
|
|
2013-09-30 13:24:42 -07:00
|
|
|
return activeTokens.getContacts();
|
2013-03-25 21:26:03 -07:00
|
|
|
} catch (IOException ioe) {
|
2013-07-08 16:29:28 -07:00
|
|
|
Log.w("PushServiceSocket", ioe);
|
2013-07-18 17:42:45 -07:00
|
|
|
return null;
|
2013-03-31 19:16:06 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-18 22:45:27 -07:00
|
|
|
public ContactTokenDetails getContactTokenDetails(String contactToken) throws IOException {
|
2013-10-01 16:26:04 -07:00
|
|
|
try {
|
2013-10-18 22:45:27 -07:00
|
|
|
String response = makeRequest(String.format(DIRECTORY_VERIFY_PATH, contactToken), "GET", null);
|
|
|
|
return new Gson().fromJson(response, ContactTokenDetails.class);
|
2013-10-01 16:26:04 -07:00
|
|
|
} catch (NotFoundException nfe) {
|
2013-10-18 22:45:27 -07:00
|
|
|
return null;
|
2013-10-01 16:26:04 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-17 15:13:00 -07:00
|
|
|
private void downloadExternalFile(String url, File localDestination)
|
|
|
|
throws IOException
|
|
|
|
{
|
2013-07-18 17:42:45 -07:00
|
|
|
URL downloadUrl = new URL(url);
|
|
|
|
HttpURLConnection connection = (HttpURLConnection) downloadUrl.openConnection();
|
|
|
|
connection.setRequestProperty("Content-Type", "application/octet-stream");
|
|
|
|
connection.setRequestMethod("GET");
|
2013-03-31 19:16:06 -07:00
|
|
|
connection.setDoInput(true);
|
|
|
|
|
2013-07-17 15:13:00 -07:00
|
|
|
try {
|
|
|
|
if (connection.getResponseCode() != 200) {
|
|
|
|
throw new IOException("Bad response: " + connection.getResponseCode());
|
|
|
|
}
|
|
|
|
|
|
|
|
OutputStream output = new FileOutputStream(localDestination);
|
2013-07-18 17:42:45 -07:00
|
|
|
InputStream input = connection.getInputStream();
|
2013-07-17 15:13:00 -07:00
|
|
|
byte[] buffer = new byte[4096];
|
|
|
|
int read;
|
|
|
|
|
|
|
|
while ((read = input.read(buffer)) != -1) {
|
|
|
|
output.write(buffer, 0, read);
|
|
|
|
}
|
|
|
|
|
|
|
|
output.close();
|
2013-07-18 17:42:45 -07:00
|
|
|
Log.w("PushServiceSocket", "Downloaded: " + url + " to: " + localDestination.getAbsolutePath());
|
2013-07-17 15:13:00 -07:00
|
|
|
} finally {
|
|
|
|
connection.disconnect();
|
2013-03-31 19:16:06 -07:00
|
|
|
}
|
2013-07-17 15:13:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private void uploadExternalFile(String method, String url, byte[] data)
|
|
|
|
throws IOException
|
|
|
|
{
|
|
|
|
URL uploadUrl = new URL(url);
|
|
|
|
HttpsURLConnection connection = (HttpsURLConnection) uploadUrl.openConnection();
|
|
|
|
connection.setDoOutput(true);
|
|
|
|
connection.setRequestMethod(method);
|
|
|
|
connection.setRequestProperty("Content-Type", "application/octet-stream");
|
|
|
|
connection.connect();
|
2013-03-31 19:16:06 -07:00
|
|
|
|
2013-07-17 15:13:00 -07:00
|
|
|
try {
|
|
|
|
OutputStream out = connection.getOutputStream();
|
|
|
|
out.write(data);
|
|
|
|
out.close();
|
2013-03-31 19:16:06 -07:00
|
|
|
|
2013-07-17 15:13:00 -07:00
|
|
|
if (connection.getResponseCode() != 200) {
|
|
|
|
throw new IOException("Bad response: " + connection.getResponseCode() + " " + connection.getResponseMessage());
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
connection.disconnect();
|
2013-03-25 21:26:03 -07:00
|
|
|
}
|
2013-07-17 15:13:00 -07:00
|
|
|
}
|
2013-03-31 19:16:06 -07:00
|
|
|
|
2013-07-17 15:13:00 -07:00
|
|
|
private Pair<String, String> makeRequestForResponseHeader(String urlFragment, String method,
|
|
|
|
String body, String responseHeader)
|
2013-07-18 17:42:45 -07:00
|
|
|
throws IOException
|
2013-07-17 15:13:00 -07:00
|
|
|
{
|
|
|
|
HttpURLConnection connection = makeBaseRequest(urlFragment, method, body);
|
|
|
|
String response = Util.readFully(connection.getInputStream());
|
|
|
|
String headerValue = connection.getHeaderField(responseHeader);
|
|
|
|
connection.disconnect();
|
2013-03-31 19:16:06 -07:00
|
|
|
|
2013-07-17 15:13:00 -07:00
|
|
|
return new Pair<String, String>(headerValue, response);
|
2013-03-25 21:26:03 -07:00
|
|
|
}
|
|
|
|
|
2013-07-08 16:29:28 -07:00
|
|
|
private String makeRequest(String urlFragment, String method, String body)
|
2013-07-18 17:42:45 -07:00
|
|
|
throws IOException
|
2013-07-17 15:13:00 -07:00
|
|
|
{
|
|
|
|
HttpURLConnection connection = makeBaseRequest(urlFragment, method, body);
|
|
|
|
String response = Util.readFully(connection.getInputStream());
|
|
|
|
|
|
|
|
connection.disconnect();
|
|
|
|
|
|
|
|
return response;
|
|
|
|
}
|
|
|
|
|
|
|
|
private HttpURLConnection makeBaseRequest(String urlFragment, String method, String body)
|
2013-07-18 17:42:45 -07:00
|
|
|
throws IOException
|
2013-07-08 16:29:28 -07:00
|
|
|
{
|
|
|
|
HttpURLConnection connection = getConnection(urlFragment, method);
|
2013-03-31 19:16:06 -07:00
|
|
|
|
|
|
|
if (body != null) {
|
|
|
|
connection.setDoOutput(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
connection.connect();
|
|
|
|
|
|
|
|
if (body != null) {
|
2013-07-08 16:29:28 -07:00
|
|
|
Log.w("PushServiceSocket", method + " -- " + body);
|
2013-03-31 19:16:06 -07:00
|
|
|
OutputStream out = connection.getOutputStream();
|
|
|
|
out.write(body.getBytes());
|
|
|
|
out.close();
|
|
|
|
}
|
|
|
|
|
2013-07-08 16:29:28 -07:00
|
|
|
if (connection.getResponseCode() == 413) {
|
|
|
|
throw new RateLimitException("Rate limit exceeded: " + connection.getResponseCode());
|
|
|
|
}
|
|
|
|
|
2013-08-02 12:48:25 -07:00
|
|
|
if (connection.getResponseCode() == 403) {
|
|
|
|
throw new AuthorizationFailedException("Authorization failed!");
|
|
|
|
}
|
|
|
|
|
2013-10-01 16:26:04 -07:00
|
|
|
if (connection.getResponseCode() == 404) {
|
|
|
|
throw new NotFoundException("Not found");
|
|
|
|
}
|
|
|
|
|
2013-03-31 19:16:06 -07:00
|
|
|
if (connection.getResponseCode() != 200) {
|
|
|
|
throw new IOException("Bad response: " + connection.getResponseCode() + " " + connection.getResponseMessage());
|
|
|
|
}
|
|
|
|
|
2013-07-17 15:13:00 -07:00
|
|
|
return connection;
|
2013-03-31 19:16:06 -07:00
|
|
|
}
|
|
|
|
|
2013-07-08 16:29:28 -07:00
|
|
|
private HttpURLConnection getConnection(String urlFragment, String method) throws IOException {
|
2013-03-25 21:26:03 -07:00
|
|
|
try {
|
|
|
|
SSLContext context = SSLContext.getInstance("TLS");
|
|
|
|
context.init(null, trustManagerFactory.getTrustManagers(), null);
|
|
|
|
|
2013-07-08 16:29:28 -07:00
|
|
|
URL url = new URL(String.format("%s%s", Release.PUSH_SERVICE_URL, urlFragment));
|
2013-10-18 22:45:27 -07:00
|
|
|
Log.w("PushServiceSocket", "Push service URL: " + Release.PUSH_SERVICE_URL);
|
|
|
|
Log.w("PushServiceSocket", "Opening URL: " + url);
|
|
|
|
|
2013-07-08 16:29:28 -07:00
|
|
|
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
|
|
|
|
|
|
|
|
if (Release.ENFORCE_SSL) {
|
|
|
|
((HttpsURLConnection)connection).setSSLSocketFactory(context.getSocketFactory());
|
|
|
|
}
|
|
|
|
|
2013-03-25 21:26:03 -07:00
|
|
|
connection.setRequestMethod(method);
|
|
|
|
connection.setRequestProperty("Content-Type", "application/json");
|
|
|
|
|
|
|
|
if (password != null) {
|
|
|
|
connection.setRequestProperty("Authorization", getAuthorizationHeader());
|
|
|
|
}
|
|
|
|
|
2013-03-31 19:16:06 -07:00
|
|
|
return connection;
|
2013-03-25 21:26:03 -07:00
|
|
|
} catch (NoSuchAlgorithmException e) {
|
|
|
|
throw new AssertionError(e);
|
|
|
|
} catch (KeyManagementException e) {
|
|
|
|
throw new AssertionError(e);
|
|
|
|
} catch (MalformedURLException e) {
|
|
|
|
throw new AssertionError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private String getAuthorizationHeader() {
|
|
|
|
try {
|
2013-08-17 19:06:04 -07:00
|
|
|
return "Basic " + Base64.encodeBytes((localNumber + ":" + password).getBytes("UTF-8"));
|
2013-03-25 21:26:03 -07:00
|
|
|
} catch (UnsupportedEncodingException e) {
|
|
|
|
throw new AssertionError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-31 19:16:06 -07:00
|
|
|
private TrustManagerFactory initializeTrustManagerFactory(Context context) {
|
|
|
|
try {
|
2013-07-10 16:33:14 -07:00
|
|
|
InputStream keyStoreInputStream = context.getResources().openRawResource(R.raw.whisper);
|
2013-03-31 19:16:06 -07:00
|
|
|
KeyStore trustStore = KeyStore.getInstance("BKS");
|
|
|
|
|
|
|
|
trustStore.load(keyStoreInputStream, "whisper".toCharArray());
|
|
|
|
|
|
|
|
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
|
|
|
|
trustManagerFactory.init(trustStore);
|
|
|
|
|
|
|
|
return trustManagerFactory;
|
|
|
|
} catch (KeyStoreException kse) {
|
|
|
|
throw new AssertionError(kse);
|
|
|
|
} catch (CertificateException e) {
|
|
|
|
throw new AssertionError(e);
|
|
|
|
} catch (NoSuchAlgorithmException e) {
|
|
|
|
throw new AssertionError(e);
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
throw new AssertionError(ioe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-18 17:42:45 -07:00
|
|
|
private static class GcmRegistrationId {
|
2013-03-25 21:26:03 -07:00
|
|
|
private String gcmRegistrationId;
|
|
|
|
|
|
|
|
public GcmRegistrationId() {}
|
|
|
|
|
|
|
|
public GcmRegistrationId(String gcmRegistrationId) {
|
|
|
|
this.gcmRegistrationId = gcmRegistrationId;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-18 17:42:45 -07:00
|
|
|
private static class AttachmentKey {
|
2013-09-08 18:19:05 -07:00
|
|
|
private long id;
|
2013-07-17 15:13:00 -07:00
|
|
|
|
2013-09-08 18:19:05 -07:00
|
|
|
public AttachmentKey(long id) {
|
2013-07-17 15:13:00 -07:00
|
|
|
this.id = id;
|
|
|
|
}
|
|
|
|
|
2013-09-08 18:19:05 -07:00
|
|
|
public long getId() {
|
2013-07-17 15:13:00 -07:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-25 21:26:03 -07:00
|
|
|
}
|