From 26a4598f3c4a76baef69ae509dd2e77b8d5c25b7 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 19 Jan 2021 15:45:41 +0100 Subject: [PATCH] automatically receive Quicksy SMS. fixes #3962 requires new version of QuicksyServer --- .travis.yml | 3 +- build.gradle | 14 +++++++ .../services/QuickConversationsService.java | 10 +++++ src/main/AndroidManifest.xml | 4 +- .../AbstractQuickConversationsService.java | 7 ++++ .../conversations/services/EventReceiver.java | 2 +- .../services/XmppConnectionService.java | 14 ++++--- .../services/QuickConversationsService.java | 30 +++++++++++++- .../conversations/ui/VerifyActivity.java | 7 ++++ .../utils/SmsRetrieverWrapper.java | 16 ++++++++ .../utils/SmsRetrieverWrapper.java | 40 +++++++++++++++++++ 11 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 src/quicksyFree/java/eu/siacs/conversations/utils/SmsRetrieverWrapper.java create mode 100644 src/quicksyPlaystore/java/eu/siacs/conversations/utils/SmsRetrieverWrapper.java diff --git a/.travis.yml b/.travis.yml index 48a836ed1..0cd250d67 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,8 +13,7 @@ before_script: - mkdir libs - wget -O libs/libwebrtc-m87.aar https://gultsch.de/files/libwebrtc-m87.aar script: - - ./gradlew assembleConversationsFreeSystemRelease - - ./gradlew assembleQuicksyFreeCompatRelease + - ./gradlew assembleDebug before_install: - yes | sdkmanager "platforms;android-28" diff --git a/build.gradle b/build.gradle index bfddf53cd..78f4c41cd 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,8 @@ configurations { conversationsFreeCompatImplementation conversationsPlaystoreCompatImplementation conversationsPlaystoreSystemImplementation + quicksyPlaystoreCompatImplementation + quicksyPlaystoreSystemImplementation quicksyFreeCompatImplementation quicksyImplementation } @@ -41,6 +43,8 @@ dependencies { } conversationsPlaystoreCompatImplementation("com.android.installreferrer:installreferrer:2.2") conversationsPlaystoreSystemImplementation("com.android.installreferrer:installreferrer:2.2") + quicksyPlaystoreCompatImplementation 'com.google.android.gms:play-services-auth-api-phone:17.0.0' + quicksyPlaystoreSystemImplementation 'com.google.android.gms:play-services-auth-api-phone:17.0.0' implementation 'org.sufficientlysecure:openpgp-api:10.0' implementation 'com.theartofdev.edmodo:android-image-cropper:2.8.0' implementation 'androidx.appcompat:appcompat:1.2.0' @@ -156,14 +160,21 @@ android { } sourceSets { + quicksyFreeSystem { + java { + srcDir 'src/quicksyFree/java' + } + } quicksyFreeCompat { java { srcDir 'src/freeCompat/java' + srcDir 'src/quicksyFree/java' } } quicksyPlaystoreCompat { java { srcDir 'src/playstoreCompat/java' + srcDir 'src/quicksyPlaystore/java' } res { srcDir 'src/playstoreCompat/res' @@ -171,6 +182,9 @@ android { } } quicksyPlaystoreSystem { + java { + srcDir 'src/quicksyPlaystore/java' + } res { srcDir 'src/quicksyPlaystore/res' } diff --git a/src/conversations/java/eu/siacs/conversations/services/QuickConversationsService.java b/src/conversations/java/eu/siacs/conversations/services/QuickConversationsService.java index 1d83a5cb5..b2a0d17f4 100644 --- a/src/conversations/java/eu/siacs/conversations/services/QuickConversationsService.java +++ b/src/conversations/java/eu/siacs/conversations/services/QuickConversationsService.java @@ -1,5 +1,10 @@ package eu.siacs.conversations.services; +import android.content.Intent; +import android.util.Log; + +import eu.siacs.conversations.Config; + public class QuickConversationsService extends AbstractQuickConversationsService { QuickConversationsService(XmppConnectionService xmppConnectionService) { @@ -25,4 +30,9 @@ public class QuickConversationsService extends AbstractQuickConversationsService public void considerSyncBackground(boolean force) { } + + @Override + public void handleSmsReceived(Intent intent) { + Log.d(Config.LOGTAG,"ignoring received SMS"); + } } \ No newline at end of file diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index c98aae041..ab7f1e000 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -72,12 +72,14 @@ - + + diff --git a/src/main/java/eu/siacs/conversations/services/AbstractQuickConversationsService.java b/src/main/java/eu/siacs/conversations/services/AbstractQuickConversationsService.java index dabd36290..d05e40ae8 100644 --- a/src/main/java/eu/siacs/conversations/services/AbstractQuickConversationsService.java +++ b/src/main/java/eu/siacs/conversations/services/AbstractQuickConversationsService.java @@ -1,9 +1,14 @@ package eu.siacs.conversations.services; +import android.content.Intent; + import eu.siacs.conversations.BuildConfig; public abstract class AbstractQuickConversationsService { + + public static final String SMS_RETRIEVED_ACTION = "com.google.android.gms.auth.api.phone.SMS_RETRIEVED"; + protected final XmppConnectionService service; public AbstractQuickConversationsService(XmppConnectionService service) { @@ -25,4 +30,6 @@ public abstract class AbstractQuickConversationsService { public abstract boolean isSynchronizing(); public abstract void considerSyncBackground(boolean force); + + public abstract void handleSmsReceived(Intent intent); } diff --git a/src/main/java/eu/siacs/conversations/services/EventReceiver.java b/src/main/java/eu/siacs/conversations/services/EventReceiver.java index 66372028b..38d12fe75 100644 --- a/src/main/java/eu/siacs/conversations/services/EventReceiver.java +++ b/src/main/java/eu/siacs/conversations/services/EventReceiver.java @@ -27,7 +27,7 @@ public class EventReceiver extends BroadcastReceiver { if (extras != null) { intentForService.putExtras(extras); } - if ("ui".equals(action) || hasEnabledAccounts(context)) { + if ("ui".equals(action) || QuickConversationsService.SMS_RETRIEVED_ACTION.equals(action) || hasEnabledAccounts(context)) { Compatibility.startService(context, intentForService); } else { Log.d(Config.LOGTAG, "EventReceiver ignored action " + intentForService.getAction()); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 9ec1c8b13..6cce735dd 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -32,10 +32,6 @@ import android.os.SystemClock; import android.preference.PreferenceManager; import android.provider.ContactsContract; import android.security.KeyChain; -import androidx.annotation.BoolRes; -import androidx.annotation.IntegerRes; -import androidx.core.app.RemoteInput; -import androidx.core.content.ContextCompat; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -44,6 +40,11 @@ import android.util.Log; import android.util.LruCache; import android.util.Pair; +import androidx.annotation.BoolRes; +import androidx.annotation.IntegerRes; +import androidx.core.app.RemoteInput; +import androidx.core.content.ContextCompat; + import com.google.common.base.Objects; import com.google.common.base.Strings; @@ -135,6 +136,7 @@ import eu.siacs.conversations.utils.WakeLockHelper; import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Namespace; +import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.OnBindListener; import eu.siacs.conversations.xmpp.OnContactStatusChanged; import eu.siacs.conversations.xmpp.OnIqPacketReceived; @@ -159,7 +161,6 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; import eu.siacs.conversations.xmpp.stanzas.PresencePacket; import me.leolin.shortcutbadger.ShortcutBadger; -import eu.siacs.conversations.xmpp.Jid; public class XmppConnectionService extends Service { @@ -633,6 +634,9 @@ public class XmppConnectionService extends Service { if (action != null) { final String uuid = intent.getStringExtra("uuid"); switch (action) { + case QuickConversationsService.SMS_RETRIEVED_ACTION: + mQuickConversationsService.handleSmsReceived(intent); + break; case ConnectivityManager.CONNECTIVITY_ACTION: if (hasInternetConnection()) { if (Config.POST_CONNECTIVITY_CHANGE_PING_INTERVAL > 0) { diff --git a/src/quicksy/java/eu/siacs/conversations/services/QuickConversationsService.java b/src/quicksy/java/eu/siacs/conversations/services/QuickConversationsService.java index f8e73b447..c5d1d7b9b 100644 --- a/src/quicksy/java/eu/siacs/conversations/services/QuickConversationsService.java +++ b/src/quicksy/java/eu/siacs/conversations/services/QuickConversationsService.java @@ -1,8 +1,10 @@ package eu.siacs.conversations.services; +import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; +import android.os.Bundle; import android.os.SystemClock; import android.preference.PreferenceManager; import android.util.Log; @@ -47,6 +49,7 @@ import eu.siacs.conversations.utils.AccountUtils; import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.PhoneNumberUtilWrapper; import eu.siacs.conversations.utils.SerialSingleThreadExecutor; +import eu.siacs.conversations.utils.SmsRetrieverWrapper; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.Jid; @@ -122,6 +125,7 @@ public class QuickConversationsService extends AbstractQuickConversationsService public void requestVerification(Phonenumber.PhoneNumber phoneNumber) { final String e164 = PhoneNumberUtilWrapper.normalize(service, phoneNumber); if (mVerificationRequestInProgress.compareAndSet(false, true)) { + SmsRetrieverWrapper.start(service); new Thread(() -> { try { final URL url = new URL(BASE_URL + "/authentication/" + e164); @@ -322,6 +326,28 @@ public class QuickConversationsService extends AbstractQuickConversationsService }); } + @Override + public void handleSmsReceived(final Intent intent) { + final Bundle extras = intent.getExtras(); + final String pin = SmsRetrieverWrapper.extractPin(extras); + if (pin == null) { + Log.d(Config.LOGTAG, "unable to extract Pin from received SMS"); + return; + } + final Account account = AccountUtils.getFirst(service); + if (account == null) { + Log.d(Config.LOGTAG, "no account configured to process PIN received by SMS"); + return; + } + verify(account, pin); + synchronized (mOnVerification) { + for (OnVerification onVerification : mOnVerification) { + onVerification.startBackgroundVerification(pin); + } + } + + } + private void considerSync(boolean forced) { Map contacts = PhoneNumberContact.load(service); @@ -429,11 +455,13 @@ public class QuickConversationsService extends AbstractQuickConversationsService void onVerificationSucceeded(); void onVerificationRetryAt(long timestamp); + + void startBackgroundVerification(String pin); } private static class Attempt { private final long timestamp; - private int hash; + private final int hash; private static final Attempt NULL = new Attempt(0, 0); diff --git a/src/quicksy/java/eu/siacs/conversations/ui/VerifyActivity.java b/src/quicksy/java/eu/siacs/conversations/ui/VerifyActivity.java index 6358e3646..1e388ce8f 100644 --- a/src/quicksy/java/eu/siacs/conversations/ui/VerifyActivity.java +++ b/src/quicksy/java/eu/siacs/conversations/ui/VerifyActivity.java @@ -316,6 +316,12 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP runOnUiThread(VERIFICATION_TIMEOUT_UPDATER); } + @Override + public void startBackgroundVerification(String pin) { + pinEntryWrapper.setPin(pin); + setVerifyingState(true); + } + //send sms again button callback @Override public void onVerificationRequestFailed(int code) { @@ -329,6 +335,7 @@ public class VerifyActivity extends XmppActivity implements ClipboardManager.OnP @Override public void onVerificationRequested() { runOnUiThread(() -> { + pinEntryWrapper.clear(); setRequestingVerificationState(false); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.we_have_sent_you_another_sms); diff --git a/src/quicksyFree/java/eu/siacs/conversations/utils/SmsRetrieverWrapper.java b/src/quicksyFree/java/eu/siacs/conversations/utils/SmsRetrieverWrapper.java new file mode 100644 index 000000000..e3e6f5a43 --- /dev/null +++ b/src/quicksyFree/java/eu/siacs/conversations/utils/SmsRetrieverWrapper.java @@ -0,0 +1,16 @@ +package eu.siacs.conversations.utils; + +import android.os.Bundle; + +import eu.siacs.conversations.services.XmppConnectionService; + +public class SmsRetrieverWrapper { + + public static void start(XmppConnectionService service) { + //nop + } + + public static String extractPin(Bundle extras) { + return null; + } +} \ No newline at end of file diff --git a/src/quicksyPlaystore/java/eu/siacs/conversations/utils/SmsRetrieverWrapper.java b/src/quicksyPlaystore/java/eu/siacs/conversations/utils/SmsRetrieverWrapper.java new file mode 100644 index 000000000..3aa38ab5f --- /dev/null +++ b/src/quicksyPlaystore/java/eu/siacs/conversations/utils/SmsRetrieverWrapper.java @@ -0,0 +1,40 @@ +package eu.siacs.conversations.utils; + +import android.content.Context; +import android.os.Bundle; +import android.util.Log; + +import com.google.android.gms.auth.api.phone.SmsRetriever; +import com.google.android.gms.auth.api.phone.SmsRetrieverClient; +import com.google.android.gms.common.api.CommonStatusCodes; +import com.google.android.gms.common.api.Status; +import com.google.android.gms.tasks.Task; +import com.google.common.base.Strings; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import eu.siacs.conversations.Config; + +public class SmsRetrieverWrapper { + + public static void start(final Context context) { + final SmsRetrieverClient client = SmsRetriever.getClient(context); + final Task task = client.startSmsRetriever(); + task.addOnSuccessListener(aVoid -> Log.d(Config.LOGTAG, "successfully started SMS retriever")); + task.addOnFailureListener(e -> Log.d(Config.LOGTAG, "unable to start SMS retriever", e)); + } + + public static String extractPin(Bundle extras) { + final Status status = extras == null ? null : (Status) extras.get(SmsRetriever.EXTRA_STATUS); + if (status != null && status.getStatusCode() == CommonStatusCodes.SUCCESS) { + Log.d(Config.LOGTAG, "Verification SMS received with status success"); + final String message = extras.getString(SmsRetriever.EXTRA_SMS_MESSAGE); + final Matcher m = Pattern.compile("(?