XmppConnection: refactor registration code. 'Open Website' on PAYMENT_REQUIRED failure

This commit is contained in:
Daniel Gultsch 2017-12-08 14:23:38 +01:00
parent d96180f0ee
commit 1b0cd77c57
2 changed files with 79 additions and 59 deletions

View file

@ -39,6 +39,7 @@ import android.widget.Toast;
import org.openintents.openpgp.util.OpenPgpUtils; import org.openintents.openpgp.util.OpenPgpUtils;
import java.net.URL;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -154,10 +155,13 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
} }
XmppConnection connection = mAccount == null ? null : mAccount.getXmppConnection(); XmppConnection connection = mAccount == null ? null : mAccount.getXmppConnection();
String url = connection != null && mAccount.getStatus() == Account.State.REGISTRATION_WEB ? connection.getWebRegistrationUrl() : null; boolean openRegistrationUrl = registerNewAccount && mAccount != null && mAccount.getStatus() == Account.State.REGISTRATION_WEB;
if (url != null && registerNewAccount && !wasDisabled) { boolean openPaymentUrl = mAccount != null && mAccount.getStatus() == Account.State.PAYMENT_REQUIRED;
final boolean redirectionWorthyStatus = openPaymentUrl || openRegistrationUrl;
URL url = connection != null && redirectionWorthyStatus ? connection.getRedirectionUrl() : null;
if (url != null && redirectionWorthyStatus && !wasDisabled) {
try { try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url.toString())));
return; return;
} catch (ActivityNotFoundException e) { } catch (ActivityNotFoundException e) {
Toast.makeText(EditAccountActivity.this,R.string.application_found_to_open_website,Toast.LENGTH_SHORT); Toast.makeText(EditAccountActivity.this,R.string.application_found_to_open_website,Toast.LENGTH_SHORT);
@ -449,11 +453,17 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
this.mSaveButton.setTextColor(getSecondaryTextColor()); this.mSaveButton.setTextColor(getSecondaryTextColor());
} }
} else { } else {
this.mSaveButton.setText(R.string.connect); XmppConnection connection = mAccount == null ? null : mAccount.getXmppConnection();
URL url = connection != null && mAccount.getStatus() == Account.State.PAYMENT_REQUIRED ? connection.getRedirectionUrl() : null;
if (url != null) {
this.mSaveButton.setText(R.string.open_website);
} else {
this.mSaveButton.setText(R.string.connect);
}
} }
} else { } else {
XmppConnection connection = mAccount == null ? null : mAccount.getXmppConnection(); XmppConnection connection = mAccount == null ? null : mAccount.getXmppConnection();
String url = connection != null && mAccount.getStatus() == Account.State.REGISTRATION_WEB ? connection.getWebRegistrationUrl() : null; URL url = connection != null && mAccount.getStatus() == Account.State.REGISTRATION_WEB ? connection.getRedirectionUrl() : null;
if (url != null && mRegisterNew.isChecked()) { if (url != null && mRegisterNew.isChecked()) {
this.mSaveButton.setText(R.string.open_website); this.mSaveButton.setText(R.string.open_website);
} else { } else {

View file

@ -20,6 +20,7 @@ import java.net.ConnectException;
import java.net.IDN; import java.net.IDN;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Socket; import java.net.Socket;
import java.net.URL; import java.net.URL;
import java.net.UnknownHostException; import java.net.UnknownHostException;
@ -141,7 +142,7 @@ public class XmppConnection implements Runnable {
private final XmppConnectionService mXmppConnectionService; private final XmppConnectionService mXmppConnectionService;
private SaslMechanism saslMechanism; private SaslMechanism saslMechanism;
private String webRegistrationUrl = null; private URL redirectionUrl = null;
private String verifiedHostname = null; private String verifiedHostname = null;
private class MyKeyManager implements X509KeyManager { private class MyKeyManager implements X509KeyManager {
@ -192,8 +193,7 @@ public class XmppConnection implements Runnable {
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.getType() == IqPacket.TYPE.RESULT) { if (packet.getType() == IqPacket.TYPE.RESULT) {
account.setOption(Account.OPTION_REGISTER, false); account.setOption(Account.OPTION_REGISTER, false);
forceCloseSocket(); throw new StateChangingError(Account.State.REGISTRATION_SUCCESSFUL);
changeStatus(Account.State.REGISTRATION_SUCCESSFUL);
} else { } else {
final List<String> PASSWORD_TOO_WEAK_MSGS = Arrays.asList( final List<String> PASSWORD_TOO_WEAK_MSGS = Arrays.asList(
"The password is too weak", "The password is too weak",
@ -211,8 +211,7 @@ public class XmppConnection implements Runnable {
state = Account.State.REGISTRATION_PASSWORD_TOO_WEAK; state = Account.State.REGISTRATION_PASSWORD_TOO_WEAK;
} }
} }
changeStatus(state); throw new StateChangingError(state);
forceCloseSocket();
} }
} }
}; };
@ -544,15 +543,21 @@ public class XmppConnection implements Runnable {
final Element failure = tagReader.readElement(nextTag); final Element failure = tagReader.readElement(nextTag);
if (Namespace.SASL.equals(failure.getNamespace())) { if (Namespace.SASL.equals(failure.getNamespace())) {
final String text = failure.findChildContent("text"); final String text = failure.findChildContent("text");
if (failure.hasChild("account-disabled") if (failure.hasChild("account-disabled") && text != null) {
&& text != null Matcher matcher = Patterns.AUTOLINK_WEB_URL.matcher(text);
&& text.contains("renew") if (matcher.find()) {
&& Config.MAGIC_CREATE_DOMAIN != null try {
&& text.contains(Config.MAGIC_CREATE_DOMAIN)) { URL url = new URL(text.substring(matcher.start(), matcher.end()));
throw new StateChangingException(Account.State.PAYMENT_REQUIRED); if (url.getProtocol().equals("https")) {
} else { this.redirectionUrl = url;
throw new StateChangingException(Account.State.UNAUTHORIZED); throw new StateChangingException(Account.State.PAYMENT_REQUIRED);
}
} catch (MalformedURLException e) {
throw new StateChangingException(Account.State.UNAUTHORIZED);
}
}
} }
throw new StateChangingException(Account.State.UNAUTHORIZED);
} else if (Namespace.TLS.equals(failure.getNamespace())) { } else if (Namespace.TLS.equals(failure.getNamespace())) {
throw new StateChangingException(Account.State.TLS_ERROR); throw new StateChangingException(Account.State.TLS_ERROR);
} else { } else {
@ -940,10 +945,14 @@ public class XmppConnection implements Runnable {
@Override @Override
public void onIqPacketReceived(final Account account, final IqPacket packet) { public void onIqPacketReceived(final Account account, final IqPacket packet) {
boolean failed = false; if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
if (packet.getType() == IqPacket.TYPE.RESULT return;
&& packet.query().hasChild("username") }
&& (packet.query().hasChild("password"))) { if (packet.getType() == IqPacket.TYPE.ERROR) {
throw new StateChangingError(Account.State.REGISTRATION_FAILED);
}
final Element query = packet.query("jabber:iq:register");
if (query.hasChild("username") && (query.hasChild("password"))) {
final IqPacket register = new IqPacket(IqPacket.TYPE.SET); final IqPacket register = new IqPacket(IqPacket.TYPE.SET);
final Element username = new Element("username").setContent(account.getUsername()); final Element username = new Element("username").setContent(account.getUsername());
final Element password = new Element("password").setContent(account.getPassword()); final Element password = new Element("password").setContent(account.getPassword());
@ -951,73 +960,74 @@ public class XmppConnection implements Runnable {
register.query().addChild(password); register.query().addChild(password);
register.setFrom(account.getJid().toBareJid()); register.setFrom(account.getJid().toBareJid());
sendUnmodifiedIqPacket(register, registrationResponseListener); sendUnmodifiedIqPacket(register, registrationResponseListener);
} else if (packet.getType() == IqPacket.TYPE.RESULT } else if (query.hasChild("x", "jabber:x:data")) {
&& (packet.query().hasChild("x", "jabber:x:data"))) { final Data data = Data.parse(query.findChild("x", "jabber:x:data"));
final Data data = Data.parse(packet.query().findChild("x", "jabber:x:data")); final Element blob = query.findChild("data", "urn:xmpp:bob");
final Element blob = packet.query().findChild("data", "urn:xmpp:bob");
final String id = packet.getId(); final String id = packet.getId();
InputStream is;
Bitmap captcha = null;
if (blob != null) { if (blob != null) {
try { try {
final String base64Blob = blob.getContent(); final String base64Blob = blob.getContent();
final byte[] strBlob = Base64.decode(base64Blob, Base64.DEFAULT); final byte[] strBlob = Base64.decode(base64Blob, Base64.DEFAULT);
InputStream stream = new ByteArrayInputStream(strBlob); is = new ByteArrayInputStream(strBlob);
captcha = BitmapFactory.decodeStream(stream);
} catch (Exception e) { } catch (Exception e) {
//ignored is = null;
} }
} else { } else {
try { try {
Field url = data.getFieldByName("url"); Field field = data.getFieldByName("url");
String urlString = url.findChildContent("value"); URL url = field != null && field.getValue() != null ? new URL(field.getValue()) : null;
URL uri = new URL(urlString); is = url != null ? url.openStream() : null;
captcha = BitmapFactory.decodeStream(uri.openConnection().getInputStream());
} catch (IOException e) { } catch (IOException e) {
Log.e(Config.LOGTAG, e.toString()); is = null;
} }
} }
if (captcha != null) { if (is != null) {
failed = !mXmppConnectionService.displayCaptchaRequest(account, id, data, captcha); Bitmap captcha = BitmapFactory.decodeStream(is);
try {
if (mXmppConnectionService.displayCaptchaRequest(account, id, data, captcha)) {
return;
}
} catch (Exception e) {
throw new StateChangingError(Account.State.REGISTRATION_FAILED);
}
} }
} else { throw new StateChangingError(Account.State.REGISTRATION_FAILED);
failed = true; } else if (query.hasChild("instructions") || query.hasChild("x",Namespace.OOB)) {
}
if (failed) {
final Element query = packet.query();
final String instructions = query.findChildContent("instructions"); final String instructions = query.findChildContent("instructions");
final Element oob = query.findChild("x", Namespace.OOB); final Element oob = query.findChild("x", Namespace.OOB);
final String url = oob == null ? null : oob.findChildContent("url"); final String url = oob == null ? null : oob.findChildContent("url");
if (url == null && instructions != null) { if (url != null) {
setAccountCreationFailed(url);
} else if (instructions != null) {
Matcher matcher = Patterns.AUTOLINK_WEB_URL.matcher(instructions); Matcher matcher = Patterns.AUTOLINK_WEB_URL.matcher(instructions);
if (matcher.find()) { if (matcher.find()) {
setAccountCreationFailed(instructions.substring(matcher.start(), matcher.end())); setAccountCreationFailed(instructions.substring(matcher.start(), matcher.end()));
} else {
setAccountCreationFailed(null);
} }
} else {
setAccountCreationFailed(url);
} }
throw new StateChangingError(Account.State.REGISTRATION_FAILED);
} }
} }
}); });
} }
private void setAccountCreationFailed(String url) { private void setAccountCreationFailed(String url) {
if (url != null && (url.toLowerCase().startsWith("http://") || url.toLowerCase().startsWith("https://"))) { if (url != null) {
changeStatus(Account.State.REGISTRATION_WEB); try {
this.webRegistrationUrl = url; this.redirectionUrl = new URL(url);
} else { if (this.redirectionUrl.getProtocol().equals("https")) {
changeStatus(Account.State.REGISTRATION_FAILED); throw new StateChangingError(Account.State.REGISTRATION_WEB);
}
} catch (MalformedURLException e) {
//fall through
}
} }
disconnect(true); throw new StateChangingError(Account.State.REGISTRATION_FAILED);
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not register. url=" + url);
} }
public String getWebRegistrationUrl() { public URL getRedirectionUrl() {
return this.webRegistrationUrl; return this.redirectionUrl;
} }
public void resetEverything() { public void resetEverything() {
@ -1025,7 +1035,7 @@ public class XmppConnection implements Runnable {
resetStreamId(); resetStreamId();
clearIqCallbacks(); clearIqCallbacks();
mStanzaQueue.clear(); mStanzaQueue.clear();
this.webRegistrationUrl = null; this.redirectionUrl = null;
synchronized (this.disco) { synchronized (this.disco) {
disco.clear(); disco.clear();
} }