From a204bf9ec1df5bb234432a6d89a67db12703baf6 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 14 Feb 2023 11:02:37 +0100 Subject: [PATCH] add support to retrieve registration --- .../xmpp/manager/RegistrationManager.java | 84 +++++++++++++++++-- .../android/xmpp/model/oob/OutOfBandData.java | 3 +- .../xmpp/model/register/Instructions.java | 10 +++ 3 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 src/main/java/im/conversations/android/xmpp/model/register/Instructions.java diff --git a/src/main/java/im/conversations/android/xmpp/manager/RegistrationManager.java b/src/main/java/im/conversations/android/xmpp/manager/RegistrationManager.java index 8b88c898c..8231c82d0 100644 --- a/src/main/java/im/conversations/android/xmpp/manager/RegistrationManager.java +++ b/src/main/java/im/conversations/android/xmpp/manager/RegistrationManager.java @@ -1,13 +1,22 @@ package im.conversations.android.xmpp.manager; import android.content.Context; +import androidx.annotation.NonNull; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import eu.siacs.conversations.utils.Patterns; +import eu.siacs.conversations.xml.Namespace; import im.conversations.android.xmpp.XmppConnection; +import im.conversations.android.xmpp.model.data.Data; +import im.conversations.android.xmpp.model.oob.OutOfBandData; +import im.conversations.android.xmpp.model.register.Instructions; +import im.conversations.android.xmpp.model.register.Password; import im.conversations.android.xmpp.model.register.Register; import im.conversations.android.xmpp.model.register.Remove; +import im.conversations.android.xmpp.model.register.Username; import im.conversations.android.xmpp.model.stanza.Iq; +import java.util.regex.Matcher; public class RegistrationManager extends AbstractManager { @@ -33,9 +42,74 @@ public class RegistrationManager extends AbstractManager { connection.sendIqPacket(iq), r -> null, MoreExecutors.directExecutor()); } - // TODO support registration - // 3 possible responses: - // 1) username + password - // 2) Captcha as shown here: https://xmpp.org/extensions/xep-0158.html#register - // 3) Redirection as show here: https://xmpp.org/extensions/xep-0077.html#redirect + public ListenableFuture getRegistration() { + final var iq = new Iq(Iq.Type.SET); + iq.addExtension(new Register()); + return Futures.transform( + connection.sendIqPacket(iq), + result -> { + final var register = result.getExtension(Register.class); + if (register == null) { + throw new IllegalStateException( + "Server did not include register in response"); + } + if (register.hasExtension(Username.class) + && register.hasExtension(Password.class)) { + return new SimpleRegistration(); + } + final var data = register.getExtension(Data.class); + if (data != null && Namespace.REGISTER.equals(data.getFormType())) { + return new ExtendedRegistration(data); + } + final var oob = register.getExtension(OutOfBandData.class); + final var instructions = register.getExtension(Instructions.class); + final String instructionsText = + instructions == null ? null : instructions.getContent(); + final String redirectUrl = oob == null ? null : oob.getURL(); + if (redirectUrl != null) { + return new RedirectRegistration(redirectUrl); + } + if (instructionsText != null) { + final Matcher matcher = Patterns.WEB_URL.matcher(instructionsText); + if (matcher.find()) { + final String instructionsUrl = + instructionsText.substring(matcher.start(), matcher.end()); + return new RedirectRegistration(instructionsUrl); + } + } + throw new IllegalStateException("No supported registration method found"); + }, + MoreExecutors.directExecutor()); + } + + private abstract static class Registration {} + + // only requires Username + Password + public static class SimpleRegistration extends Registration {} + + // Captcha as shown here: https://xmpp.org/extensions/xep-0158.html#register + public static class ExtendedRegistration extends Registration { + private final Data data; + + public ExtendedRegistration(Data data) { + this.data = data; + } + + public Data getData() { + return this.data; + } + } + + // Redirection as show here: https://xmpp.org/extensions/xep-0077.html#redirect + public static class RedirectRegistration extends Registration { + private final String url; + + public RedirectRegistration(@NonNull final String url) { + this.url = url; + } + + public @NonNull String getURL() { + return this.url; + } + } } diff --git a/src/main/java/im/conversations/android/xmpp/model/oob/OutOfBandData.java b/src/main/java/im/conversations/android/xmpp/model/oob/OutOfBandData.java index e5c8aa2a0..b324332a9 100644 --- a/src/main/java/im/conversations/android/xmpp/model/oob/OutOfBandData.java +++ b/src/main/java/im/conversations/android/xmpp/model/oob/OutOfBandData.java @@ -1,5 +1,6 @@ package im.conversations.android.xmpp.model.oob; +import com.google.common.base.Strings; import im.conversations.android.annotation.XmlElement; import im.conversations.android.xmpp.model.Extension; @@ -12,6 +13,6 @@ public class OutOfBandData extends Extension { public String getURL() { final URL url = this.getExtension(URL.class); - return url == null ? null : url.getContent(); + return url == null ? null : Strings.emptyToNull(url.getContent()); } } diff --git a/src/main/java/im/conversations/android/xmpp/model/register/Instructions.java b/src/main/java/im/conversations/android/xmpp/model/register/Instructions.java new file mode 100644 index 000000000..cd22f2a3a --- /dev/null +++ b/src/main/java/im/conversations/android/xmpp/model/register/Instructions.java @@ -0,0 +1,10 @@ +package im.conversations.android.xmpp.model.register; + +import im.conversations.android.xmpp.model.Extension; + +public class Instructions extends Extension { + + public Instructions() { + super(Instructions.class); + } +}