Compare commits

...

52 Commits

Author SHA1 Message Date
Moxie Marlinspike
35dabaf1e5 Bump version to 2.5.3
// FREEBIE
2015-02-12 13:23:53 -08:00
Jake McGinty
1aec794a34 widen LGE menu workaround constraints
// FREEBIE
2015-02-12 13:16:03 -08:00
Jake McGinty
5bd8d6c69d Check the part stream is non-null before decoding
// FREEBIE

Closes #2459
2015-02-12 10:32:53 -08:00
Moxie Marlinspike
aa26785c00 Reinclude SC provider for consistency.
// FREEBIE

Fixes #2461
2015-02-12 10:30:45 -08:00
Moxie Marlinspike
f450b37cfd Bump version to 2.5.2
// FREEBIE
2015-02-11 23:24:10 -08:00
Jake McGinty
b88e470594 prevent recipient listener Activity context leak
Resolves #2372
Resolves #2425
// FREEBIE
2015-02-11 12:50:20 -08:00
Jake McGinty
f38677794a stop giving long-living static objects Activity contexts
// FREEBIE
2015-02-11 12:50:19 -08:00
Jake McGinty
ac4db41435 lower memory consumption from previews
// FREEBIE
2015-02-11 12:50:19 -08:00
Jake McGinty
3a9d521ffe Workaround LG-related menu issues, pt. 2
fixes #2444
// FREEBIE
2015-02-11 12:44:40 -08:00
Jake McGinty
b1bf33b13b Fix SaveAttachmentTask NPE
resolves #2454
// FREEBIE
2015-02-11 11:42:36 -08:00
Moxie Marlinspike
352418d2d7 Don't notify on MMS delivery failure if message has been deleted.
// FREEBIE

Fixes #2453
2015-02-11 10:29:05 -08:00
Moxie Marlinspike
fb523985ed Bump version to 2.5.1
// FREEBIE
2015-02-09 13:45:41 -08:00
Moxie Marlinspike
7ffe6f053c Merge pull request #2435 from mcginty/dark-actionmode-popup
Fix white-on-white ActionMode popup in dark theme
2015-02-09 12:07:54 -08:00
Jake McGinty
ea77191b70 Fix white-on-white ActionMode popup
// FREEBIE
2015-02-09 12:00:52 -08:00
Moxie Marlinspike
e0b882d4d2 Merge pull request #2434 from mcginty/plurals
move plurals to strings.xml
2015-02-09 11:24:58 -08:00
Jake McGinty
10a74d6d08 move plurals to strings.xml
Resolves #2421
// FREEBIE
2015-02-09 11:19:30 -08:00
Jake McGinty
f092e85b62 Workaround for LGE-related NPEs
See: https://code.google.com/p/android/issues/detail?id=78154

Fixes #2424
Closes #2428

// FREEBIE
2015-02-09 09:15:44 -08:00
Moxie Marlinspike
8aa0f15740 Bump version to 2.5.0
// FREEBIE
2015-02-06 16:42:04 -08:00
Moxie Marlinspike
18d4d4de24 Update language translations
// FREEBIE
2015-02-06 16:21:16 -08:00
Moxie Marlinspike
b3c42dee7e Merge pull request #2416 from mcginty/better-relative-dates
more succinct relative dates
2015-02-06 16:20:23 -08:00
Moxie Marlinspike
5836f35291 Merge pull request #2400 from mcginty/mms-bad-base64-fix
Fix NPE when encrypted MMS has bad base64 encoding
2015-02-06 16:19:20 -08:00
Jake McGinty
dbd8a4083c Fix NPE when encrypted MMS has bad base64 encoding
// FREEBIE
2015-02-06 13:01:36 -08:00
Jake McGinty
0fd52ad1fe more succinct relative dates
// FREEBIE
2015-02-06 13:00:21 -08:00
Moxie Marlinspike
8031c788d9 Merge pull request #2415 from mcginty/empty-group-updates
fix empty group update messages
2015-02-05 19:49:09 -08:00
Moxie Marlinspike
10a29db93d Merge pull request #2414 from mcginty/unread-readability
increase unread visibility in conv list
2015-02-05 19:46:31 -08:00
Jake McGinty
8f3f2e6921 fix empty group update messages
// FREEBIE
2015-02-05 19:38:08 -08:00
Jake McGinty
65c262acef increase unread visibility in conv list
// FREEBIE
2015-02-05 18:41:54 -08:00
AsamK
d586893402 Also crop contact photos in ShareList
// FREEBIE
2015-02-05 14:14:48 -08:00
Jake McGinty
ba62e018db Refine icon
1) fix glow
2) improve shadows
3) fix density-inconsistent assets
2015-01-28 12:52:51 -10:00
Moxie Marlinspike
57c17e705f Fix provisioning dialog strings.
// FREEBIE

Closes #2368
2015-01-24 10:16:33 -08:00
Jake McGinty
2e253fb6a8 provisioning dialog rework
// FREEBIE
2015-01-24 10:15:47 -08:00
Moxie Marlinspike
0c32001fe4 Support for multi-device provisioning flow.
// FREEBIE
2015-01-24 10:15:47 -08:00
Jake McGinty
48f6c2c526 Fix 'indicator tab' coloring
Was previously white-on-near-white
// FREEBIE
2015-01-23 10:59:22 -10:00
Jake McGinty
39fd1e8f46 fix incoming lock asset
// FREEBIE
2015-01-21 20:06:05 -10:00
Jake McGinty
810abe0275 material actionbar and fab
// FREEBIE
2015-01-21 19:01:23 -10:00
Jake McGinty
62816ee51a rounded ImageView instead of Bitmap, crop-select
// FREEBIE
2015-01-21 17:39:54 -10:00
Calvin Hu
a0599c1639 add theme to import/export activity
closes #2359
2015-01-16 10:41:01 -10:00
Jake McGinty
8a4a1b385d libpastelog 1.0.4
// FREEBIE
2015-01-15 13:06:42 -10:00
Moxie Marlinspike
5def8ba78d Bump version to 2.4.2
// FREEBIE
2015-01-14 13:51:53 -08:00
Jake McGinty
42da687602 Revert "add theme to import/export activity"
This reverts commit e64c067636.
2015-01-14 10:23:10 -10:00
Calvin Hu
e64c067636 add theme to import/export activity 2015-01-14 10:03:02 -10:00
Calvin Hu
c89fbabbf3 refresh contacts database on new db query 2015-01-13 15:16:30 -10:00
Moxie Marlinspike
778b8b490c Merge pull request #2346 from mcginty/thumbnail-early-recycle
fix early recycling of thumbnail
2015-01-13 16:21:15 -08:00
Jake McGinty
bade52d748 fix early recycling of thumbnail
// FREEBIE
2015-01-13 14:17:03 -10:00
Moxie Marlinspike
abc322b075 Bump version to 2.4.1
// FREEBIE
2015-01-13 16:01:58 -08:00
Moxie Marlinspike
9a31c5961a Merge pull request #2341 from mcginty/mms-recv-null-text
don't fail on null received text parts
2015-01-13 12:35:22 -08:00
Jake McGinty
f536e45378 don't fail on null received text parts
Fixes #2340
// FREEBIE
2015-01-13 10:15:18 -10:00
Moxie Marlinspike
18961e6369 Merge pull request #2339 from mcginty/content-security-exception
catch content security exception
2015-01-13 12:02:24 -08:00
Jake McGinty
1505ec8c35 catch ContentProvider SecurityExceptions to avoid crashes
// FREEBIE
2015-01-13 10:00:19 -10:00
Jake McGinty
d41efdbd1c prepareMessageMedia before we encrypt
and fail more nicely when pdu composition fails

// FREEBIE

Closes #2338
2015-01-13 11:59:03 -08:00
Jake McGinty
156cb4034e don't copy data when no dataUri
Fixes #2336
// FREEBIE
2015-01-13 11:57:46 -08:00
Moxie Marlinspike
d2e188ee62 Bump version to 2.4.0
// FREEBIE
2015-01-13 11:54:36 -08:00
433 changed files with 5373 additions and 45102 deletions

View File

@@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.thoughtcrime.securesms"
android:versionCode="87"
android:versionName="2.3.3">
android:versionCode="94"
android:versionName="2.5.3">
<permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"
android:label="Access to TextSecure Secrets"
@@ -90,6 +90,21 @@
android:windowSoftInputMode="stateUnchanged"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ConfirmIdentityActivity"
android:theme="@style/TextSecure.Light.Dialog"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".DeviceProvisioningActivity"
android:theme="@style/TextSecure.DialogActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="tsdevice"/>
</intent-filter>
</activity>
<activity android:name=".MmsPreferencesActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
@@ -191,6 +206,7 @@
<activity android:name=".MediaPreviewActivity"
android:label="@string/AndroidManifest__media_preview"
android:windowSoftInputMode="stateHidden"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".DummyActivity"
@@ -208,6 +224,8 @@
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
<service android:enabled="true" android:name=".service.ApplicationMigrationService"/>
<service android:enabled="true" android:name=".service.KeyCachingService"/>
<service android:enabled="true" android:name=".service.RegistrationService"/>

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 496 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

BIN
artwork/logo-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -5,13 +5,12 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
classpath 'com.android.tools.build:gradle:1.0.1'
classpath files('libs/gradle-witness.jar')
}
}
apply plugin: 'com.android.application'
apply from: 'strip_play_services.gradle'
apply plugin: 'witness'
repositories {
@@ -30,30 +29,35 @@ repositories {
maven {
url "https://raw.github.com/whispersystems/maven/master/shortcutbadger/releases/"
}
jcenter()
}
dependencies {
compile 'me.leolin:ShortcutBadger:1.0.2-WS2'
compile 'se.emilsjolander:stickylistheaders:2.2.0'
compile 'com.google.android.gms:play-services:6.1.71'
compile 'com.google.android.gms:play-services-base:6.5.87'
compile 'com.astuetz:pagerslidingtabstrip:1.0.1'
compile 'org.w3c:smil:1.0.0'
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
compile 'com.github.chrisbanes.photoview:library:1.2.3'
compile 'com.android.support:appcompat-v7:20.0.0'
compile 'com.madgag.spongycastle:prov:1.51.0.0'
compile 'com.makeramen:roundedimageview:1.5.0'
compile 'com.afollestad:material-dialogs:0.6.1.5'
compile 'com.soundcloud.android:android-crop:0.9.10@aar'
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.melnykov:floatingactionbutton:1.1.0'
compile 'com.google.zxing:android-integration:3.1.0'
compile ('com.android.support:support-v4-preferencefragment:1.0.0@aar'){
exclude module: 'support-v4'
}
compile 'com.squareup.dagger:dagger:1.2.2'
compile ("com.doomonafireball.betterpickers:library:1.5.2") {
compile ("com.doomonafireball.betterpickers:library:1.5.3") {
exclude group: 'com.android.support', module: 'support-v4'
}
compile 'com.madgag.spongycastle:prov:1.51.0.0'
provided 'com.squareup.dagger:dagger-compiler:1.2.2'
compile 'org.whispersystems:jobmanager:0.10.0'
compile 'org.whispersystems:libpastelog:1.0.2'
compile 'org.whispersystems:libpastelog:1.0.4'
androidTestCompile 'com.squareup:fest-android:1.0.8'
androidTestCompile 'com.google.dexmaker:dexmaker:1.1'
@@ -66,28 +70,33 @@ dependencyVerification {
verify = [
'me.leolin:ShortcutBadger:027977c718035e5997035e04e05152d6c72d94df645e8b7099a274ada722bd14',
'se.emilsjolander:stickylistheaders:89146b46c96fea0e40200474a2625cda10fe94891e4128f53cdb42375091b9b6',
'com.google.android.gms:play-services:32e7d1834a1cf8fa4b17e8d359db580c286e26c1eefbf84fdb9996eac8d74919',
'com.google.android.gms:play-services-base:832cb6b3130e871db6a412c4ab585656dbcc5e7948101f190186757785703f75',
'com.astuetz:pagerslidingtabstrip:f1641396732c7132a7abb837e482e5ee2b0ebb8d10813fc52bbaec2c15c184c2',
'org.w3c:smil:085dc40f2bb249651578bfa07499fd08b16ad0886dbe2c4078586a408da62f9b',
'org.apache.httpcomponents:httpclient-android:6f56466a9bd0d42934b90bfbfe9977a8b654c058bf44a12bdc2877c4e1f033f1',
'com.github.chrisbanes.photoview:library:8b5344e206f125e7ba9d684008f36c4992d03853c57e5814125f88496126e3cc',
'com.android.support:appcompat-v7:736f576ab0b68d27bdf18b1e7931566e6d8254b73965175313e87f8866b91547',
'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a',
'com.makeramen:roundedimageview:7dda2e78c406760e5c356ccce59b0df46b5b171cf18abb891998594405021548',
'com.afollestad:material-dialogs:ccb013e6572c86cfcca433855cf0dbfbff9b5e7bb9d1f504b761a6bc6f467b60',
'com.soundcloud.android:android-crop:ffd4b973cf6e97f7d64118a0dc088df50e9066fd5634fe6911dd0c0c5d346177',
'com.android.support:appcompat-v7:5dbeb5316d0a6027d646ae552804c3baa5e3bd53f7f33db50904d51505c8a0e5',
'com.melnykov:floatingactionbutton:0679ad9f7d61eb7aeab91e8dc56358cdedd5b1c1b9c48464499ffa05c40d3985',
'com.google.zxing:android-integration:89e56aadf1164bd71e57949163c53abf90af368b51669c0d4a47a163335f95c4',
'com.android.support:support-v4-preferencefragment:5470f5872514a6226fa1fc6f4e000991f38805691c534cf0bd2778911fc773ad',
'com.squareup.dagger:dagger:789aca24537022e49f91fc6444078d9de8f1dd99e1bfb090f18491b186967883',
'com.doomonafireball.betterpickers:library:1c2dd66b0f4555e9e68427b28eed8826b7cd2e7074b8c038c88836a6aa9abe64',
'org.whispersystems:libpastelog:9798b3c93a91082c2c68542ce5b5c182e18556aebdcb7c8cebbd89eb48ac4047',
'com.doomonafireball.betterpickers:library:132ecd685c95a99e7377c4e27bfadbb2d7ed0bea995944060cd62d4369fdaf3d',
'org.whispersystems:jobmanager:01f35586c43aa3806f1c18d3d6a5a972def98103ba1a5a9ca3eec08d15f974b7',
'com.android.support:support-v4:81f2b1c2c94efd5a4ec7fcd97b6cdcd00e87a933905c5c86103c7319eb024572',
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'org.whispersystems:libpastelog:3ccf00fe1597eb8ca1e5de99b17fc225387a1b80b5bbc00ec1bc4d4f3ea9cdde',
'com.android.support:recyclerview-v7:ab2390d688601b65e2f3a0718b3d25487e61546c4e20f81eb0b033f30ca15b31',
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
'org.whispersystems:gson:08f4f7498455d1539c9233e5aac18e9b1805815ef29221572996508eb512fe51',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
'com.googlecode.libphonenumber:libphonenumber:eba17eae81dd622ea89a00a3a8c025b2f25d342e0d9644c5b62e16f15687c3ab',
'org.whispersystems:gson:08f4f7498455d1539c9233e5aac18e9b1805815ef29221572996508eb512fe51',
'org.whispersystems:axolotl-android:7617256d05aaecd7b5475cd55e42773d7079167a22ca48512bcb0f84f8473cc9',
'com.android.support:support-annotations:1aa96ef0cc4a445bfc2f93ccf762305bc57fa107b12afe9d11f3863ae8a11036',
'com.android.support:support-v4:703572d3015a088cc5604b7e38885af3d307c829d0c5ceaf8654ff41c71cd160',
'com.android.support:support-annotations:fdee2354787ef66b268e75958de3f7f6c4f8f325510a6dac9f49c929f83a63de',
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a',
]
}
@@ -95,6 +104,10 @@ android {
compileSdkVersion 21
buildToolsVersion '21.1.2'
dexOptions {
javaMaxHeapSize "4g"
}
defaultConfig {
minSdkVersion 9
targetSdkVersion 19
@@ -113,10 +126,12 @@ android {
buildTypes {
debug {
minifyEnabled false
minifyEnabled true
proguardFiles 'proguard.cfg'
}
release {
minifyEnabled false
minifyEnabled true
proguardFiles 'proguard.cfg'
signingConfig signingConfigs.release
}
}
@@ -139,7 +154,6 @@ android {
}
}
lintOptions {
abortOnError false
}

View File

@@ -42,12 +42,18 @@ message PushMessageContent {
optional AttachmentPointer avatar = 5;
}
message SyncMessageContext {
optional string destination = 1;
optional uint64 timestamp = 2;
}
enum Flags {
END_SESSION = 1;
}
optional string body = 1;
repeated AttachmentPointer attachments = 2;
optional GroupContext group = 3;
optional uint32 flags = 4;
}
optional string body = 1;
repeated AttachmentPointer attachments = 2;
optional GroupContext group = 3;
optional uint32 flags = 4;
optional SyncMessageContext sync = 5;
}

View File

@@ -1,3 +1,3 @@
all:
protoc --java_out=../src/main/java/ IncomingPushMessageSignal.proto
protoc --java_out=../src/main/java/ IncomingPushMessageSignal.proto Provisioning.proto

View File

@@ -0,0 +1,16 @@
package textsecure;
option java_package = "org.whispersystems.textsecure.internal.push";
option java_outer_classname = "ProvisioningProtos";
message ProvisionEnvelope {
optional bytes publicKey = 1;
optional bytes body = 2; // Encrypted ProvisionMessage
}
message ProvisionMessage {
optional bytes identityKeyPublic = 1;
optional bytes identityKeyPrivate = 2;
optional string number = 3;
optional string provisioningCode = 4;
}

View File

@@ -16,29 +16,37 @@
*/
package org.whispersystems.textsecure.api;
import com.google.protobuf.ByteString;
import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.IdentityKeyPair;
import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
import org.whispersystems.libaxolotl.state.PreKeyRecord;
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
import org.whispersystems.libaxolotl.util.guava.Optional;
import org.whispersystems.textsecure.api.push.ContactTokenDetails;
import org.whispersystems.textsecure.api.push.TrustStore;
import org.whispersystems.textsecure.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.textsecure.api.push.exceptions.PushNetworkException;
import org.whispersystems.textsecure.internal.push.PushServiceSocket;
import org.whispersystems.textsecure.api.push.SignedPreKeyEntity;
import org.whispersystems.textsecure.api.push.TrustStore;
import org.whispersystems.textsecure.internal.crypto.ProvisioningCipher;
import org.whispersystems.textsecure.internal.push.PushServiceSocket;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import static org.whispersystems.textsecure.internal.push.ProvisioningProtos.ProvisionMessage;
public class TextSecureAccountManager {
private final PushServiceSocket pushServiceSocket;
private final String user;
public TextSecureAccountManager(String url, TrustStore trustStore,
String user, String password)
{
this.pushServiceSocket = new PushServiceSocket(url, trustStore, user, password);
this.user = user;
}
public void setGcmId(Optional<String> gcmRegistrationId) throws IOException {
@@ -94,4 +102,26 @@ public class TextSecureAccountManager {
return this.pushServiceSocket.retrieveDirectory(contactTokens);
}
public String getNewDeviceVerificationCode() throws IOException {
return this.pushServiceSocket.getNewDeviceVerificationCode();
}
public void addDevice(String deviceIdentifier,
ECPublicKey deviceKey,
IdentityKeyPair identityKeyPair,
String code)
throws InvalidKeyException, IOException
{
ProvisioningCipher cipher = new ProvisioningCipher(deviceKey);
ProvisionMessage message = ProvisionMessage.newBuilder()
.setIdentityKeyPublic(ByteString.copyFrom(identityKeyPair.getPublicKey().serialize()))
.setIdentityKeyPrivate(ByteString.copyFrom(identityKeyPair.getPrivateKey().serialize()))
.setNumber(user)
.setProvisioningCode(code)
.build();
byte[] ciphertext = cipher.encrypt(message);
this.pushServiceSocket.sendProvisioningMessage(deviceIdentifier, ciphertext);
}
}

View File

@@ -19,6 +19,7 @@ package org.whispersystems.textsecure.api;
import android.util.Log;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.SessionBuilder;
@@ -40,6 +41,7 @@ import org.whispersystems.textsecure.internal.push.OutgoingPushMessageList;
import org.whispersystems.textsecure.internal.push.PushAttachmentData;
import org.whispersystems.textsecure.internal.push.PushBody;
import org.whispersystems.textsecure.internal.push.PushServiceSocket;
import org.whispersystems.textsecure.internal.push.SendMessageResponse;
import org.whispersystems.textsecure.internal.push.StaleDevices;
import org.whispersystems.textsecure.api.push.exceptions.UnregisteredUserException;
import org.whispersystems.textsecure.api.push.exceptions.EncapsulatedExceptions;
@@ -62,14 +64,17 @@ public class TextSecureMessageSender {
private final PushServiceSocket socket;
private final AxolotlStore store;
private final PushAddress syncAddress;
private final Optional<EventListener> eventListener;
public TextSecureMessageSender(String url, TrustStore trustStore,
String user, String password, AxolotlStore store,
String user, String password,
long userId, AxolotlStore store,
Optional<EventListener> eventListener)
{
this.socket = new PushServiceSocket(url, trustStore, user, password);
this.store = store;
this.syncAddress = new PushAddress(userId, user, null);
this.eventListener = eventListener;
}
@@ -80,8 +85,14 @@ public class TextSecureMessageSender {
public void sendMessage(PushAddress recipient, TextSecureMessage message)
throws UntrustedIdentityException, IOException
{
byte[] content = createMessageContent(message);
sendMessage(recipient, message.getTimestamp(), content);
byte[] content = createMessageContent(message);
long timestamp = message.getTimestamp();
SendMessageResponse response = sendMessage(recipient, timestamp, content);
if (response != null && response.getNeedsSync()) {
byte[] syncMessage = createSyncMessageContent(content, recipient, timestamp);
sendMessage(syncAddress, timestamp, syncMessage);
}
if (message.isEndSession()) {
store.deleteAllSessions(recipient.getRecipientId());
@@ -122,6 +133,20 @@ public class TextSecureMessageSender {
return builder.build().toByteArray();
}
private byte[] createSyncMessageContent(byte[] content, PushAddress recipient, long timestamp) {
try {
PushMessageContent.Builder builder = PushMessageContent.parseFrom(content).toBuilder();
builder.setSync(PushMessageContent.SyncMessageContext.newBuilder()
.setDestination(recipient.getNumber())
.setTimestamp(timestamp)
.build());
return builder.build().toByteArray();
} catch (InvalidProtocolBufferException e) {
throw new AssertionError(e);
}
}
private GroupContext createGroupContent(TextSecureGroup group) throws IOException {
GroupContext.Builder builder = GroupContext.newBuilder();
builder.setId(ByteString.copyFrom(group.getGroupId()));
@@ -168,15 +193,13 @@ public class TextSecureMessageSender {
}
}
private void sendMessage(PushAddress recipient, long timestamp, byte[] content)
private SendMessageResponse sendMessage(PushAddress recipient, long timestamp, byte[] content)
throws UntrustedIdentityException, IOException
{
for (int i=0;i<3;i++) {
try {
OutgoingPushMessageList messages = getEncryptedMessages(socket, recipient, timestamp, content);
socket.sendMessage(messages);
return;
return socket.sendMessage(messages);
} catch (MismatchedDevicesException mde) {
Log.w(TAG, mde);
handleMismatchedDevices(socket, recipient, mde.getMismatchedDevices());
@@ -185,6 +208,8 @@ public class TextSecureMessageSender {
handleStaleDevices(recipient, ste.getStaleDevices());
}
}
throw new IOException("Failed to resolve conflicts after 3 attempts!");
}
private List<AttachmentPointer> createAttachmentPointers(Optional<List<TextSecureAttachment>> attachments) throws IOException {
@@ -230,31 +255,31 @@ public class TextSecureMessageSender {
byte[] plaintext)
throws IOException, UntrustedIdentityException
{
PushBody masterBody = getEncryptedMessage(socket, recipient, plaintext);
List<OutgoingPushMessage> messages = new LinkedList<>();
messages.add(new OutgoingPushMessage(recipient, masterBody));
if (!recipient.equals(syncAddress)) {
PushBody masterBody = getEncryptedMessage(socket, recipient, PushAddress.DEFAULT_DEVICE_ID, plaintext);
messages.add(new OutgoingPushMessage(recipient, PushAddress.DEFAULT_DEVICE_ID, masterBody));
}
for (int deviceId : store.getSubDeviceSessions(recipient.getRecipientId())) {
PushAddress device = new PushAddress(recipient.getRecipientId(), recipient.getNumber(), deviceId, recipient.getRelay());
PushBody body = getEncryptedMessage(socket, device, plaintext);
messages.add(new OutgoingPushMessage(device, body));
PushBody body = getEncryptedMessage(socket, recipient, deviceId, plaintext);
messages.add(new OutgoingPushMessage(recipient, deviceId, body));
}
return new OutgoingPushMessageList(recipient.getNumber(), timestamp, recipient.getRelay(), messages);
}
private PushBody getEncryptedMessage(PushServiceSocket socket, PushAddress recipient, byte[] plaintext)
private PushBody getEncryptedMessage(PushServiceSocket socket, PushAddress recipient, int deviceId, byte[] plaintext)
throws IOException, UntrustedIdentityException
{
if (!store.containsSession(recipient.getRecipientId(), recipient.getDeviceId())) {
if (!store.containsSession(recipient.getRecipientId(), deviceId)) {
try {
List<PreKeyBundle> preKeys = socket.getPreKeys(recipient);
List<PreKeyBundle> preKeys = socket.getPreKeys(recipient, deviceId);
for (PreKeyBundle preKey : preKeys) {
try {
SessionBuilder sessionBuilder = new SessionBuilder(store, recipient.getRecipientId(), recipient.getDeviceId());
SessionBuilder sessionBuilder = new SessionBuilder(store, recipient.getRecipientId(), deviceId);
sessionBuilder.process(preKey);
} catch (org.whispersystems.libaxolotl.UntrustedIdentityException e) {
throw new UntrustedIdentityException("Untrusted identity key!", recipient.getNumber(), preKey.getIdentityKey());
@@ -269,7 +294,7 @@ public class TextSecureMessageSender {
}
}
TextSecureCipher cipher = new TextSecureCipher(store, recipient.getRecipientId(), recipient.getDeviceId());
TextSecureCipher cipher = new TextSecureCipher(store, recipient.getRecipientId(), deviceId);
CiphertextMessage message = cipher.encrypt(plaintext);
int remoteRegistrationId = cipher.getRemoteRegistrationId();
@@ -292,12 +317,10 @@ public class TextSecureMessageSender {
}
for (int missingDeviceId : mismatchedDevices.getMissingDevices()) {
PushAddress device = new PushAddress(recipient.getRecipientId(), recipient.getNumber(),
missingDeviceId, recipient.getRelay());
PreKeyBundle preKey = socket.getPreKey(device);
PreKeyBundle preKey = socket.getPreKey(recipient, missingDeviceId);
try {
SessionBuilder sessionBuilder = new SessionBuilder(store, device.getRecipientId(), device.getDeviceId());
SessionBuilder sessionBuilder = new SessionBuilder(store, recipient.getRecipientId(), missingDeviceId);
sessionBuilder.process(preKey);
} catch (org.whispersystems.libaxolotl.UntrustedIdentityException e) {
throw new UntrustedIdentityException("Untrusted identity key!", recipient.getNumber(), preKey.getIdentityKey());

View File

@@ -22,13 +22,11 @@ public class PushAddress {
private final long recipientId;
private final String e164number;
private final int deviceId;
private final String relay;
public PushAddress(long recipientId, String e164number, int deviceId, String relay) {
public PushAddress(long recipientId, String e164number, String relay) {
this.recipientId = recipientId;
this.e164number = e164number;
this.deviceId = deviceId;
this.relay = relay;
}
@@ -44,7 +42,29 @@ public class PushAddress {
return recipientId;
}
public int getDeviceId() {
return deviceId;
@Override
public boolean equals(Object other) {
if (other == null || !(other instanceof PushAddress)) return false;
PushAddress that = (PushAddress)other;
return this.recipientId == that.recipientId &&
equals(this.e164number, that.e164number) &&
equals(this.relay, that.relay);
}
@Override
public int hashCode() {
int hashCode = (int)this.recipientId;
if (this.e164number != null) hashCode ^= this.e164number.hashCode();
if (this.relay != null) hashCode ^= this.relay.hashCode();
return hashCode;
}
private boolean equals(String one, String two) {
if (one == null) return two == null;
return one.equals(two);
}
}

View File

@@ -0,0 +1,75 @@
package org.whispersystems.textsecure.internal.crypto;
import com.google.protobuf.ByteString;
import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.ecc.ECKeyPair;
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
import org.whispersystems.libaxolotl.kdf.HKDFv3;
import org.whispersystems.textsecure.internal.util.Util;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import static org.whispersystems.textsecure.internal.push.ProvisioningProtos.ProvisionEnvelope;
import static org.whispersystems.textsecure.internal.push.ProvisioningProtos.ProvisionMessage;
public class ProvisioningCipher {
private static final String TAG = ProvisioningCipher.class.getSimpleName();
private final ECPublicKey theirPublicKey;
public ProvisioningCipher(ECPublicKey theirPublicKey) {
this.theirPublicKey = theirPublicKey;
}
public byte[] encrypt(ProvisionMessage message) throws InvalidKeyException {
ECKeyPair ourKeyPair = Curve.generateKeyPair();
byte[] sharedSecret = Curve.calculateAgreement(theirPublicKey, ourKeyPair.getPrivateKey());
byte[] derivedSecret = new HKDFv3().deriveSecrets(sharedSecret, "TextSecure Provisioning Message".getBytes(), 64);
byte[][] parts = Util.split(derivedSecret, 32, 32);
byte[] version = {0x01};
byte[] ciphertext = getCiphertext(parts[0], message.toByteArray());
byte[] mac = getMac(parts[1], Util.join(version, ciphertext));
byte[] body = Util.join(version, ciphertext, mac);
return ProvisionEnvelope.newBuilder()
.setPublicKey(ByteString.copyFrom(ourKeyPair.getPublicKey().serialize()))
.setBody(ByteString.copyFrom(body))
.build()
.toByteArray();
}
private byte[] getCiphertext(byte[] key, byte[] message) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
return Util.join(cipher.getIV(), cipher.doFinal(message));
} catch (NoSuchAlgorithmException | NoSuchPaddingException | java.security.InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
throw new AssertionError(e);
}
}
private byte[] getMac(byte[] key, byte[] message) {
try {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key, "HmacSHA256"));
return mac.doFinal(message);
} catch (NoSuchAlgorithmException | java.security.InvalidKeyException e) {
throw new AssertionError(e);
}
}
}

View File

@@ -0,0 +1,10 @@
package org.whispersystems.textsecure.internal.push;
public class DeviceCode {
private String verificationCode;
public String getVerificationCode() {
return verificationCode;
}
}

View File

@@ -27,9 +27,9 @@ public class OutgoingPushMessage {
private int destinationRegistrationId;
private String body;
public OutgoingPushMessage(PushAddress address, PushBody body) {
public OutgoingPushMessage(PushAddress address, int deviceId, PushBody body) {
this.type = body.getType();
this.destinationDeviceId = address.getDeviceId();
this.destinationDeviceId = deviceId;
this.destinationRegistrationId = body.getRemoteRegistrationId();
this.body = Base64.encodeBytes(body.getBody());
}

View File

@@ -0,0 +1,11 @@
package org.whispersystems.textsecure.internal.push;
public class ProvisioningMessage {
private String body;
public ProvisioningMessage(String body) {
this.body = body;
}
}

View File

@@ -244,6 +244,10 @@ public final class PushMessageProtos {
* <code>RECEIPT = 5;</code>
*/
RECEIPT(5, 5),
/**
* <code>COPY = 6;</code>
*/
COPY(6, 6),
;
/**
@@ -270,6 +274,10 @@ public final class PushMessageProtos {
* <code>RECEIPT = 5;</code>
*/
public static final int RECEIPT_VALUE = 5;
/**
* <code>COPY = 6;</code>
*/
public static final int COPY_VALUE = 6;
public final int getNumber() { return value; }
@@ -282,6 +290,7 @@ public final class PushMessageProtos {
case 3: return PREKEY_BUNDLE;
case 4: return PLAINTEXT;
case 5: return RECEIPT;
case 6: return COPY;
default: return null;
}
}
@@ -1187,6 +1196,20 @@ public final class PushMessageProtos {
* <code>optional uint32 flags = 4;</code>
*/
int getFlags();
// optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
boolean hasSync();
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext getSync();
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContextOrBuilder getSyncOrBuilder();
}
/**
* Protobuf type {@code textsecure.PushMessageContent}
@@ -1270,6 +1293,19 @@ public final class PushMessageProtos {
flags_ = input.readUInt32();
break;
}
case 42: {
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.Builder subBuilder = null;
if (((bitField0_ & 0x00000008) == 0x00000008)) {
subBuilder = sync_.toBuilder();
}
sync_ = input.readMessage(org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.PARSER, extensionRegistry);
if (subBuilder != null) {
subBuilder.mergeFrom(sync_);
sync_ = subBuilder.buildPartial();
}
bitField0_ |= 0x00000008;
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -3143,6 +3179,558 @@ public final class PushMessageProtos {
// @@protoc_insertion_point(class_scope:textsecure.PushMessageContent.GroupContext)
}
public interface SyncMessageContextOrBuilder
extends com.google.protobuf.MessageOrBuilder {
// optional string destination = 1;
/**
* <code>optional string destination = 1;</code>
*/
boolean hasDestination();
/**
* <code>optional string destination = 1;</code>
*/
java.lang.String getDestination();
/**
* <code>optional string destination = 1;</code>
*/
com.google.protobuf.ByteString
getDestinationBytes();
// optional uint64 timestamp = 2;
/**
* <code>optional uint64 timestamp = 2;</code>
*/
boolean hasTimestamp();
/**
* <code>optional uint64 timestamp = 2;</code>
*/
long getTimestamp();
}
/**
* Protobuf type {@code textsecure.PushMessageContent.SyncMessageContext}
*/
public static final class SyncMessageContext extends
com.google.protobuf.GeneratedMessage
implements SyncMessageContextOrBuilder {
// Use SyncMessageContext.newBuilder() to construct.
private SyncMessageContext(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
super(builder);
this.unknownFields = builder.getUnknownFields();
}
private SyncMessageContext(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
private static final SyncMessageContext defaultInstance;
public static SyncMessageContext getDefaultInstance() {
return defaultInstance;
}
public SyncMessageContext getDefaultInstanceForType() {
return defaultInstance;
}
private final com.google.protobuf.UnknownFieldSet unknownFields;
@java.lang.Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return this.unknownFields;
}
private SyncMessageContext(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
initFields();
int mutable_bitField0_ = 0;
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder();
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
default: {
if (!parseUnknownField(input, unknownFields,
extensionRegistry, tag)) {
done = true;
}
break;
}
case 10: {
bitField0_ |= 0x00000001;
destination_ = input.readBytes();
break;
}
case 16: {
bitField0_ |= 0x00000002;
timestamp_ = input.readUInt64();
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e.getMessage()).setUnfinishedMessage(this);
} finally {
this.unknownFields = unknownFields.build();
makeExtensionsImmutable();
}
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return org.whispersystems.textsecure.internal.push.PushMessageProtos.internal_static_textsecure_PushMessageContent_SyncMessageContext_descriptor;
}
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return org.whispersystems.textsecure.internal.push.PushMessageProtos.internal_static_textsecure_PushMessageContent_SyncMessageContext_fieldAccessorTable
.ensureFieldAccessorsInitialized(
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.class, org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.Builder.class);
}
public static com.google.protobuf.Parser<SyncMessageContext> PARSER =
new com.google.protobuf.AbstractParser<SyncMessageContext>() {
public SyncMessageContext parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return new SyncMessageContext(input, extensionRegistry);
}
};
@java.lang.Override
public com.google.protobuf.Parser<SyncMessageContext> getParserForType() {
return PARSER;
}
private int bitField0_;
// optional string destination = 1;
public static final int DESTINATION_FIELD_NUMBER = 1;
private java.lang.Object destination_;
/**
* <code>optional string destination = 1;</code>
*/
public boolean hasDestination() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
/**
* <code>optional string destination = 1;</code>
*/
public java.lang.String getDestination() {
java.lang.Object ref = destination_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
if (bs.isValidUtf8()) {
destination_ = s;
}
return s;
}
}
/**
* <code>optional string destination = 1;</code>
*/
public com.google.protobuf.ByteString
getDestinationBytes() {
java.lang.Object ref = destination_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
destination_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
// optional uint64 timestamp = 2;
public static final int TIMESTAMP_FIELD_NUMBER = 2;
private long timestamp_;
/**
* <code>optional uint64 timestamp = 2;</code>
*/
public boolean hasTimestamp() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
/**
* <code>optional uint64 timestamp = 2;</code>
*/
public long getTimestamp() {
return timestamp_;
}
private void initFields() {
destination_ = "";
timestamp_ = 0L;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized != -1) return isInitialized == 1;
memoizedIsInitialized = 1;
return true;
}
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeBytes(1, getDestinationBytes());
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeUInt64(2, timestamp_);
}
getUnknownFields().writeTo(output);
}
private int memoizedSerializedSize = -1;
public int getSerializedSize() {
int size = memoizedSerializedSize;
if (size != -1) return size;
size = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(1, getDestinationBytes());
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += com.google.protobuf.CodedOutputStream
.computeUInt64Size(2, timestamp_);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
}
private static final long serialVersionUID = 0L;
@java.lang.Override
protected java.lang.Object writeReplace()
throws java.io.ObjectStreamException {
return super.writeReplace();
}
public static org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext parseFrom(java.io.InputStream input)
throws java.io.IOException {
return PARSER.parseFrom(input);
}
public static org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return PARSER.parseFrom(input, extensionRegistry);
}
public static org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return PARSER.parseDelimitedFrom(input);
}
public static org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return PARSER.parseDelimitedFrom(input, extensionRegistry);
}
public static org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return PARSER.parseFrom(input);
}
public static org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return PARSER.parseFrom(input, extensionRegistry);
}
public static Builder newBuilder() { return Builder.create(); }
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext prototype) {
return newBuilder().mergeFrom(prototype);
}
public Builder toBuilder() { return newBuilder(this); }
@java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code textsecure.PushMessageContent.SyncMessageContext}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder>
implements org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContextOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return org.whispersystems.textsecure.internal.push.PushMessageProtos.internal_static_textsecure_PushMessageContent_SyncMessageContext_descriptor;
}
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return org.whispersystems.textsecure.internal.push.PushMessageProtos.internal_static_textsecure_PushMessageContent_SyncMessageContext_fieldAccessorTable
.ensureFieldAccessorsInitialized(
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.class, org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.Builder.class);
}
// Construct using org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
private Builder(
com.google.protobuf.GeneratedMessage.BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
}
}
private static Builder create() {
return new Builder();
}
public Builder clear() {
super.clear();
destination_ = "";
bitField0_ = (bitField0_ & ~0x00000001);
timestamp_ = 0L;
bitField0_ = (bitField0_ & ~0x00000002);
return this;
}
public Builder clone() {
return create().mergeFrom(buildPartial());
}
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return org.whispersystems.textsecure.internal.push.PushMessageProtos.internal_static_textsecure_PushMessageContent_SyncMessageContext_descriptor;
}
public org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext getDefaultInstanceForType() {
return org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.getDefaultInstance();
}
public org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext build() {
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
public org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext buildPartial() {
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext result = new org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext(this);
int from_bitField0_ = bitField0_;
int to_bitField0_ = 0;
if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
to_bitField0_ |= 0x00000001;
}
result.destination_ = destination_;
if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
to_bitField0_ |= 0x00000002;
}
result.timestamp_ = timestamp_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext) {
return mergeFrom((org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext other) {
if (other == org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.getDefaultInstance()) return this;
if (other.hasDestination()) {
bitField0_ |= 0x00000001;
destination_ = other.destination_;
onChanged();
}
if (other.hasTimestamp()) {
setTimestamp(other.getTimestamp());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
public final boolean isInitialized() {
return true;
}
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext) e.getUnfinishedMessage();
throw e;
} finally {
if (parsedMessage != null) {
mergeFrom(parsedMessage);
}
}
return this;
}
private int bitField0_;
// optional string destination = 1;
private java.lang.Object destination_ = "";
/**
* <code>optional string destination = 1;</code>
*/
public boolean hasDestination() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
/**
* <code>optional string destination = 1;</code>
*/
public java.lang.String getDestination() {
java.lang.Object ref = destination_;
if (!(ref instanceof java.lang.String)) {
java.lang.String s = ((com.google.protobuf.ByteString) ref)
.toStringUtf8();
destination_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>optional string destination = 1;</code>
*/
public com.google.protobuf.ByteString
getDestinationBytes() {
java.lang.Object ref = destination_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
destination_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>optional string destination = 1;</code>
*/
public Builder setDestination(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000001;
destination_ = value;
onChanged();
return this;
}
/**
* <code>optional string destination = 1;</code>
*/
public Builder clearDestination() {
bitField0_ = (bitField0_ & ~0x00000001);
destination_ = getDefaultInstance().getDestination();
onChanged();
return this;
}
/**
* <code>optional string destination = 1;</code>
*/
public Builder setDestinationBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000001;
destination_ = value;
onChanged();
return this;
}
// optional uint64 timestamp = 2;
private long timestamp_ ;
/**
* <code>optional uint64 timestamp = 2;</code>
*/
public boolean hasTimestamp() {
return ((bitField0_ & 0x00000002) == 0x00000002);
}
/**
* <code>optional uint64 timestamp = 2;</code>
*/
public long getTimestamp() {
return timestamp_;
}
/**
* <code>optional uint64 timestamp = 2;</code>
*/
public Builder setTimestamp(long value) {
bitField0_ |= 0x00000002;
timestamp_ = value;
onChanged();
return this;
}
/**
* <code>optional uint64 timestamp = 2;</code>
*/
public Builder clearTimestamp() {
bitField0_ = (bitField0_ & ~0x00000002);
timestamp_ = 0L;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:textsecure.PushMessageContent.SyncMessageContext)
}
static {
defaultInstance = new SyncMessageContext(true);
defaultInstance.initFields();
}
// @@protoc_insertion_point(class_scope:textsecure.PushMessageContent.SyncMessageContext)
}
private int bitField0_;
// optional string body = 1;
public static final int BODY_FIELD_NUMBER = 1;
@@ -3261,11 +3849,34 @@ public final class PushMessageProtos {
return flags_;
}
// optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;
public static final int SYNC_FIELD_NUMBER = 5;
private org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext sync_;
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
public boolean hasSync() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
public org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext getSync() {
return sync_;
}
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
public org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContextOrBuilder getSyncOrBuilder() {
return sync_;
}
private void initFields() {
body_ = "";
attachments_ = java.util.Collections.emptyList();
group_ = org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.GroupContext.getDefaultInstance();
flags_ = 0;
sync_ = org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.getDefaultInstance();
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@@ -3291,6 +3902,9 @@ public final class PushMessageProtos {
if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeUInt32(4, flags_);
}
if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeMessage(5, sync_);
}
getUnknownFields().writeTo(output);
}
@@ -3316,6 +3930,10 @@ public final class PushMessageProtos {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(4, flags_);
}
if (((bitField0_ & 0x00000008) == 0x00000008)) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(5, sync_);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@@ -3426,6 +4044,7 @@ public final class PushMessageProtos {
if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
getAttachmentsFieldBuilder();
getGroupFieldBuilder();
getSyncFieldBuilder();
}
}
private static Builder create() {
@@ -3450,6 +4069,12 @@ public final class PushMessageProtos {
bitField0_ = (bitField0_ & ~0x00000004);
flags_ = 0;
bitField0_ = (bitField0_ & ~0x00000008);
if (syncBuilder_ == null) {
sync_ = org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.getDefaultInstance();
} else {
syncBuilder_.clear();
}
bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
@@ -3503,6 +4128,14 @@ public final class PushMessageProtos {
to_bitField0_ |= 0x00000004;
}
result.flags_ = flags_;
if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
to_bitField0_ |= 0x00000008;
}
if (syncBuilder_ == null) {
result.sync_ = sync_;
} else {
result.sync_ = syncBuilder_.build();
}
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
@@ -3556,6 +4189,9 @@ public final class PushMessageProtos {
if (other.hasFlags()) {
setFlags(other.getFlags());
}
if (other.hasSync()) {
mergeSync(other.getSync());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
@@ -4047,6 +4683,123 @@ public final class PushMessageProtos {
return this;
}
// optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;
private org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext sync_ = org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.getDefaultInstance();
private com.google.protobuf.SingleFieldBuilder<
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext, org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.Builder, org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContextOrBuilder> syncBuilder_;
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
public boolean hasSync() {
return ((bitField0_ & 0x00000010) == 0x00000010);
}
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
public org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext getSync() {
if (syncBuilder_ == null) {
return sync_;
} else {
return syncBuilder_.getMessage();
}
}
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
public Builder setSync(org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext value) {
if (syncBuilder_ == null) {
if (value == null) {
throw new NullPointerException();
}
sync_ = value;
onChanged();
} else {
syncBuilder_.setMessage(value);
}
bitField0_ |= 0x00000010;
return this;
}
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
public Builder setSync(
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.Builder builderForValue) {
if (syncBuilder_ == null) {
sync_ = builderForValue.build();
onChanged();
} else {
syncBuilder_.setMessage(builderForValue.build());
}
bitField0_ |= 0x00000010;
return this;
}
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
public Builder mergeSync(org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext value) {
if (syncBuilder_ == null) {
if (((bitField0_ & 0x00000010) == 0x00000010) &&
sync_ != org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.getDefaultInstance()) {
sync_ =
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.newBuilder(sync_).mergeFrom(value).buildPartial();
} else {
sync_ = value;
}
onChanged();
} else {
syncBuilder_.mergeFrom(value);
}
bitField0_ |= 0x00000010;
return this;
}
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
public Builder clearSync() {
if (syncBuilder_ == null) {
sync_ = org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.getDefaultInstance();
onChanged();
} else {
syncBuilder_.clear();
}
bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
public org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.Builder getSyncBuilder() {
bitField0_ |= 0x00000010;
onChanged();
return getSyncFieldBuilder().getBuilder();
}
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
public org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContextOrBuilder getSyncOrBuilder() {
if (syncBuilder_ != null) {
return syncBuilder_.getMessageOrBuilder();
} else {
return sync_;
}
}
/**
* <code>optional .textsecure.PushMessageContent.SyncMessageContext sync = 5;</code>
*/
private com.google.protobuf.SingleFieldBuilder<
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext, org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.Builder, org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContextOrBuilder>
getSyncFieldBuilder() {
if (syncBuilder_ == null) {
syncBuilder_ = new com.google.protobuf.SingleFieldBuilder<
org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext, org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContext.Builder, org.whispersystems.textsecure.internal.push.PushMessageProtos.PushMessageContent.SyncMessageContextOrBuilder>(
sync_,
getParentForChildren(),
isClean());
sync_ = null;
}
return syncBuilder_;
}
// @@protoc_insertion_point(builder_scope:textsecure.PushMessageContent)
}
@@ -4078,6 +4831,11 @@ public final class PushMessageProtos {
private static
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_textsecure_PushMessageContent_GroupContext_fieldAccessorTable;
private static com.google.protobuf.Descriptors.Descriptor
internal_static_textsecure_PushMessageContent_SyncMessageContext_descriptor;
private static
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_textsecure_PushMessageContent_SyncMessageContext_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
@@ -4088,28 +4846,32 @@ public final class PushMessageProtos {
static {
java.lang.String[] descriptorData = {
"\n\037IncomingPushMessageSignal.proto\022\ntexts" +
"ecure\"\224\002\n\031IncomingPushMessageSignal\0228\n\004t" +
"ecure\"\236\002\n\031IncomingPushMessageSignal\0228\n\004t" +
"ype\030\001 \001(\0162*.textsecure.IncomingPushMessa" +
"geSignal.Type\022\016\n\006source\030\002 \001(\t\022\024\n\014sourceD" +
"evice\030\007 \001(\r\022\r\n\005relay\030\003 \001(\t\022\021\n\ttimestamp\030" +
"\005 \001(\004\022\017\n\007message\030\006 \001(\014\"d\n\004Type\022\013\n\007UNKNOW" +
"\005 \001(\004\022\017\n\007message\030\006 \001(\014\"n\n\004Type\022\013\n\007UNKNOW" +
"N\020\000\022\016\n\nCIPHERTEXT\020\001\022\020\n\014KEY_EXCHANGE\020\002\022\021\n" +
"\rPREKEY_BUNDLE\020\003\022\r\n\tPLAINTEXT\020\004\022\013\n\007RECEI" +
"PT\020\005\"\207\004\n\022PushMessageContent\022\014\n\004body\030\001 \001(" +
"\t\022E\n\013attachments\030\002 \003(\01320.textsecure.Push",
"MessageContent.AttachmentPointer\022:\n\005grou" +
"p\030\003 \001(\0132+.textsecure.PushMessageContent." +
"GroupContext\022\r\n\005flags\030\004 \001(\r\032A\n\021Attachmen" +
"tPointer\022\n\n\002id\030\001 \001(\006\022\023\n\013contentType\030\002 \001(" +
"\t\022\013\n\003key\030\003 \001(\014\032\363\001\n\014GroupContext\022\n\n\002id\030\001 " +
"\001(\014\022>\n\004type\030\002 \001(\01620.textsecure.PushMessa" +
"geContent.GroupContext.Type\022\014\n\004name\030\003 \001(" +
"\t\022\017\n\007members\030\004 \003(\t\022@\n\006avatar\030\005 \001(\01320.tex" +
"tsecure.PushMessageContent.AttachmentPoi" +
"nter\"6\n\004Type\022\013\n\007UNKNOWN\020\000\022\n\n\006UPDATE\020\001\022\013\n",
"\007DELIVER\020\002\022\010\n\004QUIT\020\003\"\030\n\005Flags\022\017\n\013END_SES" +
"SION\020\001B@\n+org.whispersystems.textsecure." +
"internal.pushB\021PushMessageProtos"
"PT\020\005\022\010\n\004COPY\020\006\"\206\005\n\022PushMessageContent\022\014\n" +
"\004body\030\001 \001(\t\022E\n\013attachments\030\002 \003(\01320.texts",
"ecure.PushMessageContent.AttachmentPoint" +
"er\022:\n\005group\030\003 \001(\0132+.textsecure.PushMessa" +
"geContent.GroupContext\022\r\n\005flags\030\004 \001(\r\022?\n" +
"\004sync\030\005 \001(\01321.textsecure.PushMessageCont" +
"ent.SyncMessageContext\032A\n\021AttachmentPoin" +
"ter\022\n\n\002id\030\001 \001(\006\022\023\n\013contentType\030\002 \001(\t\022\013\n\003" +
"key\030\003 \001(\014\032\363\001\n\014GroupContext\022\n\n\002id\030\001 \001(\014\022>" +
"\n\004type\030\002 \001(\01620.textsecure.PushMessageCon" +
"tent.GroupContext.Type\022\014\n\004name\030\003 \001(\t\022\017\n\007" +
"members\030\004 \003(\t\022@\n\006avatar\030\005 \001(\01320.textsecu",
"re.PushMessageContent.AttachmentPointer\"" +
"6\n\004Type\022\013\n\007UNKNOWN\020\000\022\n\n\006UPDATE\020\001\022\013\n\007DELI" +
"VER\020\002\022\010\n\004QUIT\020\003\032<\n\022SyncMessageContext\022\023\n" +
"\013destination\030\001 \001(\t\022\021\n\ttimestamp\030\002 \001(\004\"\030\n" +
"\005Flags\022\017\n\013END_SESSION\020\001B@\n+org.whispersy" +
"stems.textsecure.internal.pushB\021PushMess" +
"ageProtos"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -4127,7 +4889,7 @@ public final class PushMessageProtos {
internal_static_textsecure_PushMessageContent_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_textsecure_PushMessageContent_descriptor,
new java.lang.String[] { "Body", "Attachments", "Group", "Flags", });
new java.lang.String[] { "Body", "Attachments", "Group", "Flags", "Sync", });
internal_static_textsecure_PushMessageContent_AttachmentPointer_descriptor =
internal_static_textsecure_PushMessageContent_descriptor.getNestedTypes().get(0);
internal_static_textsecure_PushMessageContent_AttachmentPointer_fieldAccessorTable = new
@@ -4140,6 +4902,12 @@ public final class PushMessageProtos {
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_textsecure_PushMessageContent_GroupContext_descriptor,
new java.lang.String[] { "Id", "Type", "Name", "Members", "Avatar", });
internal_static_textsecure_PushMessageContent_SyncMessageContext_descriptor =
internal_static_textsecure_PushMessageContent_descriptor.getNestedTypes().get(2);
internal_static_textsecure_PushMessageContent_SyncMessageContext_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_textsecure_PushMessageContent_SyncMessageContext_descriptor,
new java.lang.String[] { "Destination", "Timestamp", });
return null;
}
};

View File

@@ -79,11 +79,15 @@ public class PushServiceSocket {
private static final String CREATE_ACCOUNT_VOICE_PATH = "/v1/accounts/voice/code/%s";
private static final String VERIFY_ACCOUNT_PATH = "/v1/accounts/code/%s";
private static final String REGISTER_GCM_PATH = "/v1/accounts/gcm/";
private static final String PREKEY_METADATA_PATH = "/v2/keys/";
private static final String PREKEY_PATH = "/v2/keys/%s";
private static final String PREKEY_DEVICE_PATH = "/v2/keys/%s/%s";
private static final String SIGNED_PREKEY_PATH = "/v2/keys/signed";
private static final String PROVISIONING_CODE_PATH = "/v1/devices/provisioning/code";
private static final String PROVISIONING_MESSAGE_PATH = "/v1/provisioning/%s";
private static final String DIRECTORY_TOKENS_PATH = "/v1/directory/tokens";
private static final String DIRECTORY_VERIFY_PATH = "/v1/directory/%s";
private static final String MESSAGE_PATH = "/v1/messages/%s";
@@ -120,6 +124,16 @@ public class PushServiceSocket {
"PUT", new Gson().toJson(signalingKeyEntity));
}
public String getNewDeviceVerificationCode() throws IOException {
String responseText = makeRequest(PROVISIONING_CODE_PATH, "GET", null);
return new Gson().fromJson(responseText, DeviceCode.class).getVerificationCode();
}
public void sendProvisioningMessage(String destination, byte[] body) throws IOException {
makeRequest(String.format(PROVISIONING_MESSAGE_PATH, destination), "PUT",
new Gson().toJson(new ProvisioningMessage(Base64.encodeBytes(body))));
}
public void sendReceipt(String destination, long messageId, String relay) throws IOException {
String path = String.format(RECEIPT_PATH, destination, messageId);
@@ -139,11 +153,15 @@ public class PushServiceSocket {
makeRequest(REGISTER_GCM_PATH, "DELETE", null);
}
public void sendMessage(OutgoingPushMessageList bundle)
public SendMessageResponse sendMessage(OutgoingPushMessageList bundle)
throws IOException
{
try {
makeRequest(String.format(MESSAGE_PATH, bundle.getDestination()), "PUT", new Gson().toJson(bundle));
String responseText = makeRequest(String.format(MESSAGE_PATH, bundle.getDestination()), "PUT", new Gson().toJson(bundle));
if (responseText == null) return new SendMessageResponse(false);
else return new Gson().fromJson(responseText, SendMessageResponse.class);
} catch (NotFoundException nfe) {
throw new UnregisteredUserException(bundle.getDestination(), nfe);
}
@@ -183,9 +201,9 @@ public class PushServiceSocket {
return preKeyStatus.getCount();
}
public List<PreKeyBundle> getPreKeys(PushAddress destination) throws IOException {
public List<PreKeyBundle> getPreKeys(PushAddress destination, int deviceIdInteger) throws IOException {
try {
String deviceId = String.valueOf(destination.getDeviceId());
String deviceId = String.valueOf(deviceIdInteger);
if (deviceId.equals("1"))
deviceId = "*";
@@ -231,10 +249,10 @@ public class PushServiceSocket {
}
}
public PreKeyBundle getPreKey(PushAddress destination) throws IOException {
public PreKeyBundle getPreKey(PushAddress destination, int deviceId) throws IOException {
try {
String path = String.format(PREKEY_DEVICE_PATH, destination.getNumber(),
String.valueOf(destination.getDeviceId()));
String.valueOf(deviceId));
if (!Util.isEmpty(destination.getRelay())) {
path = path + "?relay=" + destination.getRelay();

View File

@@ -0,0 +1,16 @@
package org.whispersystems.textsecure.internal.push;
public class SendMessageResponse {
private boolean needsSync;
public SendMessageResponse() {}
public SendMessageResponse(boolean needsSync) {
this.needsSync = needsSync;
}
public boolean getNeedsSync() {
return needsSync;
}
}

View File

@@ -25,6 +25,19 @@ import java.security.SecureRandom;
public class Util {
public static byte[] join(byte[]... input) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (byte[] part : input) {
baos.write(part);
}
return baos.toByteArray();
} catch (IOException e) {
throw new AssertionError(e);
}
}
public static byte[][] split(byte[] input, int firstLength, int secondLength) {
byte[][] parts = new byte[2][];

7
proguard.cfg Normal file
View File

@@ -0,0 +1,7 @@
-keepattributes **
-keep class !android.support.v7.internal.view.menu.**,** {*;}
-dontpreverify
-dontoptimize
-dontshrink
-dontwarn **

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_enabled="false" android:color="@color/gray27"/>
<item android:color="@color/gray95"/>
</selector>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_enabled="false" android:color="@color/gray27"/>
<item android:color="@color/gray50"/>
</selector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 509 B

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 B

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 759 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 789 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Some files were not shown because too many files have changed in this diff Show More