diff options
author | Christian Schneppe <christian.schneppe@pix-art.de> | 2020-01-24 17:08:30 +0100 |
---|---|---|
committer | Christian Schneppe <christian.schneppe@pix-art.de> | 2020-01-24 17:08:30 +0100 |
commit | 6d74698aec0a2728ac1a88d27b3eb0aa7904e4c9 (patch) | |
tree | 25e7ba81c3fb8bcce0c46adbb44e7c553c8cecff /src/main/java | |
parent | f4a207e859999b49603efcea548f4a09546bb569 (diff) |
support registration via pars tokens
Diffstat (limited to '')
8 files changed, 133 insertions, 51 deletions
diff --git a/src/main/java/de/pixart/messenger/entities/Account.java b/src/main/java/de/pixart/messenger/entities/Account.java index fe31dbf07..edd0fdc8c 100644 --- a/src/main/java/de/pixart/messenger/entities/Account.java +++ b/src/main/java/de/pixart/messenger/entities/Account.java @@ -56,6 +56,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable public static final String RESOURCE = "resource"; public static final String PINNED_MECHANISM_KEY = "pinned_mechanism"; + public static final String PRE_AUTH_REGISTRATION_TOKEN = "pre_auth_registration"; public static final int OPTION_USETLS = 0; public static final int OPTION_DISABLED = 1; @@ -655,6 +656,7 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable REGISTRATION_CONFLICT(true, false), REGISTRATION_NOT_SUPPORTED(true, false), REGISTRATION_PLEASE_WAIT(true, false), + REGISTRATION_INVALID_TOKEN(true, false), REGISTRATION_PASSWORD_TOO_WEAK(true, false), TLS_ERROR, INCOMPATIBLE_SERVER, @@ -719,6 +721,8 @@ public class Account extends AbstractEntity implements AvatarService.Avatarable return R.string.account_status_regis_success; case REGISTRATION_NOT_SUPPORTED: return R.string.account_status_regis_not_sup; + case REGISTRATION_INVALID_TOKEN: + return R.string.account_status_regis_invalid_token; case TLS_ERROR: return R.string.account_status_tls_error; case INCOMPATIBLE_SERVER: diff --git a/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java b/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java index fc669171f..4758f59bc 100644 --- a/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java +++ b/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java @@ -351,6 +351,16 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat if (mInitMode && mAccount != null && !mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY)) { xmppConnectionService.deleteAccount(mAccount); } + + final boolean magicCreate = mAccount != null && mAccount.isOptionSet(Account.OPTION_MAGIC_CREATE) && !mAccount.isOptionSet(Account.OPTION_LOGGED_IN_SUCCESSFULLY); + final Jid jid = mAccount == null ? null : mAccount.getJid(); + + if (SignupUtils.isSupportTokenRegistry() && jid != null && magicCreate && !jid.getDomain().equals(Config.MAGIC_CREATE_DOMAIN)) { + final Intent intent = SignupUtils.getTokenRegistrationIntent(this, jid.getDomain(), mAccount.getKey(Account.PRE_AUTH_REGISTRATION_TOKEN)); + startActivity(intent); + return; + } + if (xmppConnectionService.getAccounts().size() == 0 && Config.MAGIC_CREATE_DOMAIN != null) { Intent intent = SignupUtils.getSignUpIntent(this); startActivity(intent); @@ -897,6 +907,9 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat return false; } switch (item.getItemId()) { + case android.R.id.home: + deleteAccountAndReturnIfNecessary(); + break; case R.id.action_import_backup: if (hasStoragePermission(REQUEST_IMPORT_BACKUP)) { startActivity(new Intent(this, ImportBackupActivity.class)); diff --git a/src/main/java/de/pixart/messenger/ui/MagicCreateActivity.java b/src/main/java/de/pixart/messenger/ui/MagicCreateActivity.java index 372c2bc27..af7b965af 100644 --- a/src/main/java/de/pixart/messenger/ui/MagicCreateActivity.java +++ b/src/main/java/de/pixart/messenger/ui/MagicCreateActivity.java @@ -1,6 +1,5 @@ package de.pixart.messenger.ui; -import android.app.AlertDialog; import android.content.Intent; import android.content.pm.ActivityInfo; import android.os.Bundle; @@ -9,12 +8,11 @@ import android.text.TextWatcher; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.CheckBox; import android.widget.CompoundButton; -import android.widget.EditText; -import android.widget.Spinner; -import android.widget.TextView; + +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.widget.Toolbar; +import androidx.databinding.DataBindingUtil; import java.security.SecureRandom; import java.util.Arrays; @@ -23,18 +21,20 @@ import java.util.List; import de.pixart.messenger.Config; import de.pixart.messenger.R; +import de.pixart.messenger.databinding.ActivityMagicCreateBinding; import de.pixart.messenger.entities.Account; import de.pixart.messenger.utils.CryptoHelper; import rocks.xmpp.addr.Jid; public class MagicCreateActivity extends XmppActivity implements TextWatcher, AdapterView.OnItemSelectedListener, CompoundButton.OnCheckedChangeListener { - private TextView mFullJidDisplay; - private EditText mUsername; - private CheckBox mUseOwnProvider; - private Spinner mServer; private boolean useOwnProvider = false; - String domain = null; + public static final String EXTRA_DOMAIN = "domain"; + public static final String EXTRA_PRE_AUTH = "pre_auth"; + + private ActivityMagicCreateBinding binding; + private String domain; + private String preAuth; @Override protected void refreshUiReal() { @@ -57,30 +57,31 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad @Override protected void onCreate(final Bundle savedInstanceState) { + final Intent data = getIntent(); + this.domain = data == null ? null : data.getStringExtra(EXTRA_DOMAIN); + this.preAuth = data == null ? null : data.getStringExtra(EXTRA_PRE_AUTH); if (getResources().getBoolean(R.bool.portrait_only)) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } super.onCreate(savedInstanceState); - setContentView(R.layout.activity_magic_create); - setSupportActionBar(findViewById(R.id.toolbar)); - configureActionBar(getSupportActionBar()); - mFullJidDisplay = findViewById(R.id.full_jid); + this.binding = DataBindingUtil.setContentView(this, R.layout.activity_magic_create); final List<String> domains = Arrays.asList(getResources().getStringArray(R.array.domains)); Collections.sort(domains, String::compareToIgnoreCase); final ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_selectable_list_item, domains); int defaultServer = adapter.getPosition("blabber.im"); - mUsername = findViewById(R.id.username); - mUseOwnProvider = findViewById(R.id.use_own); - mUseOwnProvider.setOnCheckedChangeListener(this); - mServer = findViewById(R.id.server); - mServer.setAdapter(adapter); - mServer.setSelection(defaultServer); - mServer.setOnItemSelectedListener(this); + binding.useOwn.setOnCheckedChangeListener(this); + binding.server.setAdapter(adapter); + binding.server.setSelection(defaultServer); + binding.server.setOnItemSelectedListener(this); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - Button next = findViewById(R.id.create_account); - next.setOnClickListener(v -> { + setSupportActionBar((Toolbar) this.binding.toolbar); + configureActionBar(getSupportActionBar(), this.domain == null); + if (domain != null) { + binding.instructions.setText(getString(R.string.magic_create_text_on_x, domain)); + } + binding.createAccount.setOnClickListener(v -> { try { - String username = mUsername.getText().toString(); + final String username = binding.username.getText().toString(); if (domain == null && !useOwnProvider) { domain = Config.MAGIC_CREATE_DOMAIN; } @@ -89,10 +90,10 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad } Jid jid = Jid.of(username.toLowerCase(), domain, null); if (!jid.getEscapedLocal().equals(jid.getLocal()) || username.length() < 3) { - mUsername.setError(getString(R.string.invalid_username)); - mUsername.requestFocus(); + binding.username.setError(getString(R.string.invalid_username)); + binding.username.requestFocus(); } else { - mUsername.setError(null); + binding.username.setError(null); Account account = xmppConnectionService.findAccountByJid(jid); String password = CryptoHelper.createPassword(new SecureRandom()); if (account == null) { @@ -100,6 +101,9 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad account.setOption(Account.OPTION_REGISTER, true); account.setOption(Account.OPTION_DISABLED, true); account.setOption(Account.OPTION_MAGIC_CREATE, true); + if (this.preAuth != null) { + account.setKey(Account.PRE_AUTH_REGISTRATION_TOKEN, this.preAuth); + } xmppConnectionService.createAccount(account); } Intent intent = new Intent(MagicCreateActivity.this, EditAccountActivity.class); @@ -108,7 +112,6 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad intent.putExtra("existing", false); intent.putExtra("useownprovider", useOwnProvider); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(getString(R.string.create_account)); builder.setCancelable(false); @@ -131,13 +134,15 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad } }); builder.create().show(); + StartConversationActivity.addInviteUri(intent, getIntent()); + startActivity(intent); } } catch (IllegalArgumentException e) { - mUsername.setError(getString(R.string.invalid_username)); - mUsername.requestFocus(); + binding.username.setError(getString(R.string.invalid_username)); + binding.username.requestFocus(); } }); - mUsername.addTextChangedListener(this); + binding.username.addTextChangedListener(this); } @Override @@ -157,43 +162,45 @@ public class MagicCreateActivity extends XmppActivity implements TextWatcher, Ad @Override public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { - generateJID(mUsername.getText().toString()); + generateJID(binding.username.getText().toString()); } @Override public void onNothingSelected(AdapterView<?> adapterView) { - generateJID(mUsername.getText().toString()); + generateJID(binding.username.getText().toString()); } private void generateJID(String s) { - domain = mServer.getSelectedItem().toString(); + domain = binding.server.getSelectedItem().toString(); if (s.trim().length() > 0) { try { - mFullJidDisplay.setVisibility(View.VISIBLE); - if (domain == null) { - domain = Config.MAGIC_CREATE_DOMAIN; + binding.fullJid.setVisibility(View.VISIBLE); + final Jid jid; + if (this.domain == null) { + jid = Jid.ofLocalAndDomain(s, Config.MAGIC_CREATE_DOMAIN); + } else { + jid = Jid.ofLocalAndDomain(s, this.domain); } - Jid jid = Jid.of(s.toLowerCase(), domain, null); - mFullJidDisplay.setText(getString(R.string.your_full_jid_will_be, jid.toEscapedString())); + binding.fullJid.setText(getString(R.string.your_full_jid_will_be, jid.toEscapedString())); } catch (IllegalArgumentException e) { - mFullJidDisplay.setVisibility(View.INVISIBLE); + binding.fullJid.setVisibility(View.INVISIBLE); } } else { - mFullJidDisplay.setVisibility(View.INVISIBLE); + binding.fullJid.setVisibility(View.INVISIBLE); } } @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (mUseOwnProvider.isChecked()) { - mServer.setEnabled(false); - mFullJidDisplay.setVisibility(View.GONE); + if (binding.useOwn.isChecked()) { + binding.server.setEnabled(false); + binding.fullJid.setVisibility(View.GONE); useOwnProvider = true; } else { - mServer.setEnabled(true); - mFullJidDisplay.setVisibility(View.VISIBLE); + binding.server.setEnabled(true); + binding.fullJid.setVisibility(View.VISIBLE); useOwnProvider = false; } } -} +}
\ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/UriHandlerActivity.java b/src/main/java/de/pixart/messenger/ui/UriHandlerActivity.java index 9b53d5d24..bb34e7958 100644 --- a/src/main/java/de/pixart/messenger/ui/UriHandlerActivity.java +++ b/src/main/java/de/pixart/messenger/ui/UriHandlerActivity.java @@ -7,14 +7,17 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import androidx.core.content.ContextCompat; -import androidx.appcompat.app.AppCompatActivity; +import android.util.Log; import android.widget.Toast; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.content.ContextCompat; + import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import de.pixart.messenger.Config; import de.pixart.messenger.R; import de.pixart.messenger.persistance.DatabaseBackend; import de.pixart.messenger.utils.SignupUtils; @@ -85,6 +88,17 @@ public class UriHandlerActivity extends AppCompatActivity { final Intent intent; final XmppUri xmppUri = new XmppUri(uri); final List<Jid> accounts = DatabaseBackend.getInstance(this).getAccountJids(true); + if (SignupUtils.isSupportTokenRegistry() && xmppUri.isJidValid() && xmppUri.isAction(XmppUri.ACTION_REGISTER)) { + final String preauth = xmppUri.getParamater("preauth"); + final Jid jid = xmppUri.getJid(); + if (jid.isDomainJid()) { + intent = SignupUtils.getTokenRegistrationIntent(this, jid.getDomain(), preauth); + startActivity(intent); + return; + } + Log.d(Config.LOGTAG, "attempting to register on " + jid + " with preauth=" + preauth); + return; + } if (accounts.size() == 0) { if (xmppUri.isJidValid()) { intent = SignupUtils.getSignUpIntent(this); diff --git a/src/main/java/de/pixart/messenger/utils/Namespace.java b/src/main/java/de/pixart/messenger/utils/Namespace.java index a6624309a..1fbe82a81 100644 --- a/src/main/java/de/pixart/messenger/utils/Namespace.java +++ b/src/main/java/de/pixart/messenger/utils/Namespace.java @@ -37,4 +37,6 @@ public final class Namespace { public static final String BOOKMARKS2_COMPAT = BOOKMARKS2 + "#compat"; public static final String DISCO_ITEMS = "http://jabber.org/protocol/disco#items"; public static final String DISCO_INFO = "http://jabber.org/protocol/disco#info"; + public static final String INVITE = "urn:xmpp:invite"; + public static final String PARS = "urn:xmpp:pars:0"; } diff --git a/src/main/java/de/pixart/messenger/utils/SignupUtils.java b/src/main/java/de/pixart/messenger/utils/SignupUtils.java index 1fc368fa4..21c62cffa 100644 --- a/src/main/java/de/pixart/messenger/utils/SignupUtils.java +++ b/src/main/java/de/pixart/messenger/utils/SignupUtils.java @@ -8,12 +8,24 @@ import de.pixart.messenger.entities.Account; import de.pixart.messenger.services.XmppConnectionService; import de.pixart.messenger.ui.ConversationsActivity; import de.pixart.messenger.ui.EditAccountActivity; +import de.pixart.messenger.ui.MagicCreateActivity; import de.pixart.messenger.ui.ManageAccountActivity; import de.pixart.messenger.ui.StartConversationActivity; import de.pixart.messenger.ui.WelcomeActivity; public class SignupUtils { + public static boolean isSupportTokenRegistry() { + return true; + } + + public static Intent getTokenRegistrationIntent(final Activity activity, String domain, String preauth) { + final Intent intent = new Intent(activity, MagicCreateActivity.class); + intent.putExtra(MagicCreateActivity.EXTRA_DOMAIN, domain); + intent.putExtra(MagicCreateActivity.EXTRA_PRE_AUTH, preauth); + return intent; + } + public static Intent getSignUpIntent(final Activity activity) { final Intent intent = new Intent(activity, WelcomeActivity.class); return intent; diff --git a/src/main/java/de/pixart/messenger/utils/XmppUri.java b/src/main/java/de/pixart/messenger/utils/XmppUri.java index fa83fb8f4..322b1f760 100644 --- a/src/main/java/de/pixart/messenger/utils/XmppUri.java +++ b/src/main/java/de/pixart/messenger/utils/XmppUri.java @@ -31,7 +31,9 @@ public class XmppUri { public static final String OMEMO_URI_PARAM = "omemo-sid-"; private static final String OTR_URI_PARAM = "otr-fingerprint"; public static final String ACTION_JOIN = "join"; + public static final String ACTION_MESSAGE = "message"; + public static final String ACTION_REGISTER = "register"; public static Pattern XMPP_URI = Patterns.XMPP_PATTERN; @@ -199,6 +201,10 @@ public class XmppUri { return parameters.get("name"); } + public String getParamater(String key) { + return this.parameters.get(key); + } + public List<Fingerprint> getFingerprints() { return this.fingerprints; } diff --git a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java index 617a2e3ad..b8cddc170 100644 --- a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java +++ b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java @@ -114,6 +114,7 @@ public class XmppConnection implements Runnable { public void onIqPacketReceived(Account account, IqPacket packet) { if (packet.getType() == IqPacket.TYPE.RESULT) { account.setOption(Account.OPTION_REGISTER, false); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": successfully registered new account on server"); throw new StateChangingError(Account.State.REGISTRATION_SUCCESSFUL); } else { final List<String> PASSWORD_TOO_WEAK_MSGS = Arrays.asList( @@ -876,7 +877,7 @@ public class XmppConnection implements Runnable { sendStartTLS(); } else if (this.streamFeatures.hasChild("register") && account.isOptionSet(Account.OPTION_REGISTER)) { if (isSecure) { - sendRegistryRequest(); + register(); } else { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to find STARTTLS for registration process " + XmlHelper.printElementNames(this.streamFeatures)); throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER); @@ -950,6 +951,25 @@ public class XmppConnection implements Runnable { return mechanisms; } + private void register() { + final String preAuth = account.getKey(Account.PRE_AUTH_REGISTRATION_TOKEN); + if (preAuth != null && features.invite()) { + final IqPacket preAuthRequest = new IqPacket(IqPacket.TYPE.SET); + preAuthRequest.addChild("preauth", Namespace.PARS).setAttribute("token", preAuth); + sendUnmodifiedIqPacket(preAuthRequest, (account, response) -> { + if (response.getType() == IqPacket.TYPE.RESULT) { + sendRegistryRequest(); + } else { + final Element error = response.getError(); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": failed to pre auth. " + error); + throw new StateChangingError(Account.State.REGISTRATION_INVALID_TOKEN); + } + }, true); + } else { + sendRegistryRequest(); + } + } + private void sendRegistryRequest() { final IqPacket register = new IqPacket(IqPacket.TYPE.GET); register.query(Namespace.REGISTER); @@ -1899,6 +1919,10 @@ public class XmppConnection implements Runnable { return hasDiscoFeature(Jid.of(account.getServer()), Namespace.REGISTER); } + public boolean invite() { + return connection.streamFeatures != null && connection.streamFeatures.hasChild("register", Namespace.INVITE); + } + public boolean sm() { return streamId != null || (connection.streamFeatures != null && connection.streamFeatures.hasChild("sm")); |