Try all gateway translations options

Send jabber:iq:gateway if we're responding to that and fetch translated
response as the JID.  Otherwise use JID escaping if supported.
Otherwise fall back to the dumb ancient % escaping.
This commit is contained in:
Stephen Paul Weber 2022-03-07 15:08:07 -05:00
parent 1d0e285816
commit 7845ded2d3
No known key found for this signature in database
GPG Key ID: D11C2911CE519CDE
3 changed files with 78 additions and 51 deletions

View File

@ -145,7 +145,7 @@ 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.OnGatewayPromptResult;
import eu.siacs.conversations.xmpp.OnGatewayResult;
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
import eu.siacs.conversations.xmpp.OnMessageAcknowledged;
@ -4656,19 +4656,20 @@ public class XmppConnectionService extends Service {
}
}
public void fetchGatewayPrompt(Account account, final Jid jid, final OnGatewayPromptResult callback) {
IqPacket request = new IqPacket(IqPacket.TYPE.GET);
public void fetchFromGateway(Account account, final Jid jid, final String input, final OnGatewayResult callback) {
IqPacket request = new IqPacket(input == null ? IqPacket.TYPE.GET : IqPacket.TYPE.SET);
request.setTo(jid);
request.query("jabber:iq:gateway");
sendIqPacket(account, request, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.getType() == IqPacket.TYPE.RESULT) {
callback.onGatewayPromptResult(packet.query().findChildContent("prompt"), null);
} else {
Element error = packet.findChild("error");
callback.onGatewayPromptResult(null, error == null ? null : error.findChildContent("text"));
}
Element query = request.query("jabber:iq:gateway");
if (input != null) {
Element prompt = query.addChild("prompt");
prompt.setContent(input);
}
sendIqPacket(account, request, (Account acct, IqPacket packet) -> {
if (packet.getType() == IqPacket.TYPE.RESULT) {
callback.onGatewayResult(packet.query().findChildContent(input == null ? "prompt" : "jid"), null);
} else {
Element error = packet.findChild("error");
callback.onGatewayResult(null, error == null ? null : error.findChildContent("text"));
}
});
}

View File

@ -43,7 +43,7 @@ import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
import eu.siacs.conversations.ui.util.DelayedHintHelper;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnGatewayPromptResult;
import eu.siacs.conversations.xmpp.OnGatewayResult;
public class EnterJidDialog extends DialogFragment implements OnBackendConnected, TextWatcher {
@ -161,7 +161,7 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
for (final Contact contact : account.getRoster().getContacts()) {
if (contact.showInRoster() && (contact.getPresences().anyIdentity("gateway", null) || contact.getPresences().anySupport("jabber:iq:gateway"))) {
context.xmppConnectionService.fetchGatewayPrompt(account, contact.getJid(), (final String prompt, String errorMessage) -> {
context.xmppConnectionService.fetchFromGateway(account, contact.getJid(), null, (final String prompt, String errorMessage) -> {
if (prompt == null) return;
context.runOnUiThread(() -> {
@ -216,41 +216,67 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
return;
}
final Jid accountJid = accountJid();
final Jid contactJid;
try {
contactJid = Jid.ofEscaped(binding.jid.getText().toString());
} catch (final IllegalArgumentException e) {
binding.jidLayout.setError(getActivity().getString(R.string.invalid_jid));
return;
}
if (!issuedWarning && sanityCheckJid) {
if (contactJid.isDomainJid()) {
binding.jidLayout.setError(
getActivity().getString(R.string.this_looks_like_a_domain));
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add_anway);
issuedWarning = true;
return;
}
if (suspiciousSubDomain(contactJid.getDomain().toEscapedString())) {
binding.jidLayout.setError(
getActivity().getString(R.string.this_looks_like_channel));
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add_anway);
issuedWarning = true;
return;
}
}
if (mListener != null) {
try {
if (mListener.onEnterJidDialogPositive(accountJid, contactJid)) {
dialog.dismiss();
final OnGatewayResult finish = (final String jidString, final String errorMessage) -> {
getActivity().runOnUiThread(() -> {
if (errorMessage != null) {
binding.jidLayout.setError(errorMessage);
return;
}
} catch (JidError error) {
binding.jidLayout.setError(error.toString());
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add);
issuedWarning = false;
}
if (jidString == null) {
binding.jidLayout.setError(getActivity().getString(R.string.invalid_jid));
return;
}
final Jid contactJid;
try {
contactJid = Jid.ofEscaped(jidString);
} catch (final IllegalArgumentException e) {
binding.jidLayout.setError(getActivity().getString(R.string.invalid_jid));
return;
}
if (!issuedWarning && sanityCheckJid) {
if (contactJid.isDomainJid()) {
binding.jidLayout.setError(getActivity().getString(R.string.this_looks_like_a_domain));
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add_anway);
issuedWarning = true;
return;
}
if (suspiciousSubDomain(contactJid.getDomain().toEscapedString())) {
binding.jidLayout.setError(getActivity().getString(R.string.this_looks_like_channel));
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add_anway);
issuedWarning = true;
return;
}
}
if (mListener != null) {
try {
if (mListener.onEnterJidDialogPositive(accountJid, contactJid)) {
dialog.dismiss();
}
} catch (JidError error) {
binding.jidLayout.setError(error.toString());
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add);
issuedWarning = false;
}
}
});
};
Pair<String,Pair<Jid,Presence>> p = gatewayListAdapter.getSelected();
if (p == null) {
finish.onGatewayResult(binding.jid.getText().toString(), null);
} else if (p.first != null) { // Gateway already responsed to jabber:iq:gateway once
final Account acct = ((XmppActivity) getActivity()).xmppConnectionService.findAccountByJid(accountJid);
((XmppActivity) getActivity()).xmppConnectionService.fetchFromGateway(acct, p.second.first, binding.jid.getText().toString(), finish);
} else if (p.second.first.isDomainJid() && p.second.second.getServiceDiscoveryResult().getFeatures().contains("jid\\20escaping")) {
finish.onGatewayResult(Jid.ofLocalAndDomain(binding.jid.getText().toString(), p.second.first.getDomain().toString()).toString(), null);
} else if (p.second.first.isDomainJid()) {
finish.onGatewayResult(Jid.ofLocalAndDomain(binding.jid.getText().toString().replace("@", "%"), p.second.first.getDomain().toString()).toString(), null);
} else {
finish.onGatewayResult(null, null);
}
}

View File

@ -1,7 +1,7 @@
package eu.siacs.conversations.xmpp;
public interface OnGatewayPromptResult {
public interface OnGatewayResult {
// if prompt is null, there was an error
// errorText may or may not be set
public void onGatewayPromptResult(String prompt, String errorText);
public void onGatewayResult(String prompt, String errorText);
}