From 10c4a105bb8c42874547613bd36b3714ff6e09b4 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Wed, 2 Apr 2025 18:14:49 +0200 Subject: [PATCH] feat: Move to addTransport / addTransportFromQr API (#3676), remove AEAP message (#3698) --- CHANGELOG.md | 1 + .../java/com/b44t/messenger/DcContext.java | 1 - .../b44t/messenger/rpc/EnteredLoginParam.java | 171 ++++++++++++++++++ src/main/java/com/b44t/messenger/rpc/Rpc.java | 23 ++- .../securesms/InstantOnboardingActivity.java | 26 +-- .../securesms/RegistrationActivity.java | 85 +++++---- .../securesms/connect/DcHelper.java | 1 - src/main/res/values/strings.xml | 2 +- 8 files changed, 256 insertions(+), 54 deletions(-) create mode 100644 src/main/java/com/b44t/messenger/rpc/EnteredLoginParam.java diff --git a/CHANGELOG.md b/CHANGELOG.md index fe0b2d7f7..cd1093f9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * hide superfluous "Show Classic E-mails" advanced setting for chatmail * remove mostly non-telling transport addresses when referring to a contact; the contact's profile gives a much better overview +* Disable AEAP to enable us to overhaul some things - there are big changes underway in this area, which will come in a few months ## v1.56.1 2025-03 diff --git a/src/main/java/com/b44t/messenger/DcContext.java b/src/main/java/com/b44t/messenger/DcContext.java index 009d5d999..a428659af 100644 --- a/src/main/java/com/b44t/messenger/DcContext.java +++ b/src/main/java/com/b44t/messenger/DcContext.java @@ -118,7 +118,6 @@ public class DcContext { public native void setStockTranslation (int stockId, String translation); public native String getBlobdir (); public native String getLastError (); - public native void configure (); public native void stopOngoingProcess (); public native int isConfigured (); public native boolean open (String passphrase); diff --git a/src/main/java/com/b44t/messenger/rpc/EnteredLoginParam.java b/src/main/java/com/b44t/messenger/rpc/EnteredLoginParam.java new file mode 100644 index 000000000..9c65486d5 --- /dev/null +++ b/src/main/java/com/b44t/messenger/rpc/EnteredLoginParam.java @@ -0,0 +1,171 @@ +package com.b44t.messenger.rpc; + +public class EnteredLoginParam { + // Email address. + private final String addr; + + // Password. + private final String password; + + // ============ IMAP settings ============ + + // Server hostname or IP address. + private final String imapServer; + + // Server port. + private final int imapPort; + + // Socket security. + private final SocketSecurity imapSecurity; + + // Username. + private final String imapUser; + + // ============ SMTP settings ============ + + // Server hostname or IP address. + private final String smtpServer; + + // Server port. + private final int smtpPort; + + // Socket security. + private final SocketSecurity smtpSecurity; + + // Username. + private final String smtpUser; + + // SMTP Password. Only needs to be specified if different than IMAP password. + private final String smtpPassword; + + // TLS options: whether to allow invalid certificates and/or + // invalid hostnames + private final EnteredCertificateChecks certificateChecks; + + // If true, login via OAUTH2 (not recommended anymore) + private final boolean oauth2; + + public EnteredLoginParam(String addr, + String password, + String imapServer, + int imapPort, + SocketSecurity imapSecurity, + String imapUser, + String smtpServer, + int smtpPort, + SocketSecurity smtpSecurity, + String smtpUser, + String smtpPassword, + EnteredCertificateChecks certificateChecks, + boolean oauth2) { + this.addr = addr; + this.password = password; + this.imapServer = imapServer; + this.imapPort = imapPort; + this.imapSecurity = imapSecurity; + this.imapUser = imapUser; + this.smtpServer = smtpServer; + this.smtpPort = smtpPort; + this.smtpSecurity = smtpSecurity; + this.smtpUser = smtpUser; + this.smtpPassword = smtpPassword; + this.certificateChecks = certificateChecks; + this.oauth2 = oauth2; + } + + public String getAddr() { + return addr; + } + + public String getPassword() { + return password; + } + + public String getImapServer() { + return imapServer; + } + + public int getImapPort() { + return imapPort; + } + + public SocketSecurity getImapSecurity() { + return imapSecurity; + } + + public String getImapUser() { + return imapUser; + } + + public String getSmtpServer() { + return smtpServer; + } + + public int getSmtpPort() { + return smtpPort; + } + + public SocketSecurity getSmtpSecurity() { + return smtpSecurity; + } + + public String getSmtpUser() { + return smtpUser; + } + + public String getSmtpPassword() { + return smtpPassword; + } + + public EnteredCertificateChecks getCertificateChecks() { + return certificateChecks; + } + + public boolean isOauth2() { + return oauth2; + } + + public enum EnteredCertificateChecks { + automatic, strict, acceptInvalidCertificates, + } + + public static EnteredCertificateChecks certificateChecksFromInt(int position) { + switch (position) { + case 0: + return EnteredCertificateChecks.automatic; + case 1: + return EnteredCertificateChecks.strict; + case 2: + return EnteredCertificateChecks.acceptInvalidCertificates; + } + throw new IllegalArgumentException("Invalid certificate position: " + position); + } + + public enum SocketSecurity { + // Unspecified socket security, select automatically. + automatic, + + // TLS connection. + ssl, + + // STARTTLS connection. + starttls, + + // No TLS, plaintext connection. + plain, + } + + public static SocketSecurity socketSecurityFromInt(int position) { + switch (position) { + case 0: + return SocketSecurity.automatic; + case 1: + return SocketSecurity.ssl; + case 2: + return SocketSecurity.starttls; + case 3: + return SocketSecurity.plain; + } + throw new IllegalArgumentException("Invalid socketSecurity position: " + position); + } +} diff --git a/src/main/java/com/b44t/messenger/rpc/Rpc.java b/src/main/java/com/b44t/messenger/rpc/Rpc.java index 2b588cdc9..ba7e37746 100644 --- a/src/main/java/com/b44t/messenger/rpc/Rpc.java +++ b/src/main/java/com/b44t/messenger/rpc/Rpc.java @@ -1,5 +1,7 @@ package com.b44t.messenger.rpc; +import android.util.Log; + import com.b44t.messenger.DcJsonrpcInstance; import com.b44t.messenger.util.concurrent.SettableFuture; import com.google.gson.Gson; @@ -8,12 +10,16 @@ import com.google.gson.JsonElement; import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; +import org.thoughtcrime.securesms.qr.QrShowFragment; + import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; public class Rpc { + private final static String TAG = Rpc.class.getSimpleName(); + private final Map> requestFutures = new ConcurrentHashMap<>(); private final DcJsonrpcInstance dcJsonrpcInstance; private int requestId = 0; @@ -38,7 +44,14 @@ public class Rpc { } if (response.error != null) { - future.setException(new RpcException(response.error.toString())); + String message; + try { + message = response.error.getAsJsonObject().get("message").getAsString(); + } catch (Exception e) { + Log.e(TAG, "Can't get response error message: " + e); + message = response.error.toString(); + } + future.setException(new RpcException(message)); } else if (response.result != null) { future.set(response.result); } else { @@ -137,6 +150,14 @@ public class Rpc { return getResult("add_account").getAsInt(); } + public void addTransportFromQr(int accountId, String qrCode) throws RpcException { + getResult("add_transport_from_qr", accountId, qrCode); + } + + public void addTransport(int accountId, EnteredLoginParam param) throws RpcException { + getResult("add_transport", accountId, param); + } + private static class Request { private final String jsonrpc = "2.0"; public final String method; diff --git a/src/main/java/org/thoughtcrime/securesms/InstantOnboardingActivity.java b/src/main/java/org/thoughtcrime/securesms/InstantOnboardingActivity.java index 276ba4a5d..5830eac8a 100644 --- a/src/main/java/org/thoughtcrime/securesms/InstantOnboardingActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/InstantOnboardingActivity.java @@ -32,6 +32,8 @@ import androidx.loader.app.LoaderManager; import com.b44t.messenger.DcContext; import com.b44t.messenger.DcEvent; import com.b44t.messenger.DcLot; +import com.b44t.messenger.rpc.Rpc; +import com.b44t.messenger.rpc.RpcException; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.transition.Transition; @@ -408,14 +410,7 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements if (eventId == DcContext.DC_EVENT_CONFIGURE_PROGRESS) { long progress = event.getData1Int(); - if (progress==0/*error/aborted*/) { - progressError(event.getData2Str()); - } else if (progress<1000/*progress in permille*/) { - progressUpdate((int)progress); - } else if (progress==1000/*done*/) { - DcHelper.getAccounts(this).startIo(); - progressSuccess(); - } + progressUpdate((int)progress); } } @@ -499,14 +494,13 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements DcHelper.getEventCenter(this).captureNextError(); new Thread(() -> { - if (!dcContext.setConfigFromQr(qrCode)) { - Util.runOnMain(() -> { - progressError(dcContext.getLastError()); - }); - return; - } - DcHelper.getAccounts(this).stopIo(); - dcContext.configure(); + Rpc rpc = DcHelper.getRpc(this); + try { + rpc.addTransportFromQr(dcContext.getAccountId(), qrCode); + progressSuccess(); + } catch (RpcException e) { + Util.runOnMain(() -> progressError(e.getMessage())); + } }).start(); } diff --git a/src/main/java/org/thoughtcrime/securesms/RegistrationActivity.java b/src/main/java/org/thoughtcrime/securesms/RegistrationActivity.java index 8a01dc900..b83c2e9b4 100644 --- a/src/main/java/org/thoughtcrime/securesms/RegistrationActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/RegistrationActivity.java @@ -46,6 +46,9 @@ import androidx.constraintlayout.widget.Group; import com.b44t.messenger.DcContext; import com.b44t.messenger.DcEvent; import com.b44t.messenger.DcProvider; +import com.b44t.messenger.rpc.EnteredLoginParam; +import com.b44t.messenger.rpc.Rpc; +import com.b44t.messenger.rpc.RpcException; import com.b44t.messenger.util.concurrent.ListenableFuture; import com.b44t.messenger.util.concurrent.SettableFuture; import com.google.android.material.textfield.TextInputEditText; @@ -280,19 +283,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve int id = item.getItemId(); if (id == R.id.do_register) { - String oldAddr = DcHelper.getSelfAddr(this); - String newAddr = emailInput.getText().toString(); - if (!TextUtils.isEmpty(oldAddr) - && !TextUtils.equals(oldAddr.toLowerCase(Locale.ROOT), newAddr.toLowerCase(Locale.ROOT))) { - // Tell the user about AEAP if they are about to change their address - new AlertDialog.Builder(this) - .setMessage(getString(R.string.aeap_explanation, oldAddr, newAddr)) - .setNegativeButton(R.string.cancel, (d, w) -> {}) - .setPositiveButton(R.string.perm_continue, (d, w) -> do_register()) - .show(); - } else { - do_register(); - } + do_register(); return true; } else if (id == android.R.id.home) { // handle close button click here @@ -616,9 +607,42 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve // calling configure() results in // receiving multiple DC_EVENT_CONFIGURE_PROGRESS events - DcHelper.getAccounts(this).stopIo(); DcHelper.getEventCenter(this).captureNextError(); - DcHelper.getContext(this).configure(); + + EnteredLoginParam param = new EnteredLoginParam( + getParam(R.id.email_text, true), + getParam(R.id.password_text, false), + getParam(R.id.imap_server_text, true), + Util.objectToInt(getParam(R.id.imap_port_text, true)), + EnteredLoginParam.socketSecurityFromInt(imapSecurity.getSelectedItemPosition()), + getParam(R.id.imap_login_text, false), + getParam(R.id.smtp_server_text, true), + Util.objectToInt(getParam(R.id.smtp_port_text, true)), + EnteredLoginParam.socketSecurityFromInt(smtpSecurity.getSelectedItemPosition()), + getParam(R.id.smtp_login_text, false), + getParam(R.id.smtp_password_text, false), + EnteredLoginParam.certificateChecksFromInt(certCheck.getSelectedItemPosition()), + authMethod.getSelectedItemPosition() == 1 + ); + + new Thread(() -> { + Rpc rpc = DcHelper.getRpc(this); + try { + rpc.addTransport(DcHelper.getContext(this).getAccountId(), param); + DcHelper.getAccounts(this).startIo(); + DcHelper.getEventCenter(this).endCaptureNextError(); + progressDialog.dismiss(); + Intent conversationList = new Intent(getApplicationContext(), ConversationListActivity.class); + startActivity(conversationList); + finish(); + } catch (RpcException e) { + Util.runOnMain(() -> { + DcHelper.getEventCenter(this).endCaptureNextError(); + progressDialog.dismiss(); + WelcomeActivity.maybeShowConfigurationError(this, e.getMessage()); + }); + } + }).start(); } private void setConfig(@IdRes int viewId, String configTarget, boolean doTrim) { @@ -630,6 +654,15 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve DcHelper.getContext(this).setConfig(configTarget, value.isEmpty()? null : value); } + private String getParam(@IdRes int viewId, boolean doTrim) { + TextInputEditText view = findViewById(viewId); + String value = view.getText().toString(); + if(doTrim) { + value = value.trim(); + } + return value.isEmpty()? null : value; + } + private void stopLoginProcess() { DcHelper.getContext(this).stopOngoingProcess(); } @@ -637,25 +670,9 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve @Override public void handleEvent(@NonNull DcEvent event) { if (event.getId()==DcContext.DC_EVENT_CONFIGURE_PROGRESS) { - long progress = event.getData1Int(); - if (progress==0/*error/aborted*/) { - DcHelper.getAccounts(this).startIo(); // start-io is also needed on errors to make previous config work in case of changes - DcHelper.getEventCenter(this).endCaptureNextError(); - progressDialog.dismiss(); - WelcomeActivity.maybeShowConfigurationError(this, event.getData2Str()); - } - else if (progress<1000/*progress in permille*/) { - int percent = (int)progress / 10; - progressDialog.setMessage(getResources().getString(R.string.one_moment)+String.format(" %d%%", percent)); - } - else if (progress==1000/*done*/) { - DcHelper.getAccounts(this).startIo(); - DcHelper.getEventCenter(this).endCaptureNextError(); - progressDialog.dismiss(); - Intent conversationList = new Intent(getApplicationContext(), ConversationListActivity.class); - startActivity(conversationList); - finish(); - } + long progress = event.getData1Int(); // progress in permille + int percent = (int)progress / 10; + progressDialog.setMessage(getResources().getString(R.string.one_moment)+String.format(" %d%%", percent)); } } } diff --git a/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java b/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java index e1c3c2493..143df3b4c 100644 --- a/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java +++ b/src/main/java/org/thoughtcrime/securesms/connect/DcHelper.java @@ -237,7 +237,6 @@ public class DcHelper { dcContext.setStockTranslation(120, context.getString(R.string.qrshow_join_group_hint).replace("\"", "")); dcContext.setStockTranslation(121, context.getString(R.string.connectivity_not_connected)); dcContext.setStockTranslation(122, context.getString(R.string.aeap_addr_changed)); - dcContext.setStockTranslation(123, context.getString(R.string.aeap_explanation)); dcContext.setStockTranslation(162, context.getString(R.string.multidevice_qr_subtitle)); dcContext.setStockTranslation(163, context.getString(R.string.multidevice_transfer_done_devicemsg)); diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index a638379b2..95659b957 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -531,7 +531,7 @@ Send Message %1$s changed their address from %2$s to %3$s - + You changed your email address from %1$s to %2$s.\n\nIf you now send a message to a verified group, contacts there will automatically replace the old with your new address.\n\nIt\'s highly advised to set up your old email provider to forward all emails to your new email address. Otherwise you might miss messages of contacts who did not get your new address yet.