(2017/1/8)
** Updated iqregisterx.zip and bob.zip to store the bob data in Base64 to be consistent with smack library and XEP document.**
and pass DataForm to onCaptchaRequested instead of Form for better backend processing
Below is an extraction of the implementation for aTalk to support server inBand registration with catpcha protection. The implementation requires access to method AccountManager#getRegistrationInfo(); however it is currently implemented as “private” not accessible to outside. Because of this, I have to duplicate the getRegistrationInfo() function in AccountManager in my source.as shown below.
Appreciate the Smack development team would consider to expose the method public and make info as returned object.
I have implemented the “XEP-0231: Bits of Binary” and attached the source with this message. The smack development team is welcome to include them in the standard smack library release.
======================================================
/**
-
Perform the InBand Registration for the accountId on the defined XMPP connection by pps.
-
Registration can either be:
-
- simple username and password or
-
- With catpcha protection using form with embedded catpcha image if available, else the
-
image is retrieved from the given url in the form.
-
@param pps
-
The protocolServiceProvider.
-
@param accountId
-
The username accountID for registration.
-
@throws XMPPException,
-
SmackException
*/
public boolean registerAccount(ProtocolProviderServiceJabberImpl pps, AccountID accountId)
throws XMPPException, SmackException
{
XMPPTCPConnection connection = pps.getConnection();
try {
if (!connection.isConnected())
connection.connect();AccountManager accountManager = AccountManager.getInstance(connection);
if (accountManager.isSupported()) {
Registration info = getRegistrationInfo(connection);
if (info != null) {
Form form = null;
DataForm dataFrom = info.getExtension(DataForm.ELEMENT, DataForm.NAMESPACE);Bitmap captcha = null;
Bob bob = info.getExtension(Bob.ELEMENT, Bob.NAMESPACE);
if (bob != null) {
byte[] bytData = Base64.decode(bob.getData());
InputStream stream = new ByteArrayInputStream(bytData);
captcha = BitmapFactory.decodeStream(stream);
}
else {
FormField urlField = (FormField) dataFrom.getField(“url”);
if (urlField != null) {
String urlString = urlField.getValues().get(0);
URL uri = new URL(urlString);
captcha = BitmapFactory.decodeStream(uri.openConnection().getInputStream());
}
}
if ((captcha != null) && (dataFrom != null)) {
pps.mOnCaptchaRequested.onCaptchaRequested(connection, accountId, dataFrom , captcha);
}
else
return false;
}
else {
String userName = accountId.getUserID();
Localpart username = JidCreate.bareFrom(userName).getLocalpartOrNull();
accountManager.sensitiveOperationOverInsecureConnection(false);
accountManager.createAccount(username, password);
}
}
else
return false;
}
catch (IOException | InterruptedException ex) {
// No response received within reply timeout. Timeout was 5000ms (~5s).
// Rethrow XMPPException will trigger a re-login / registration dialog
String exMsg = ex.getMessage();
XMPPError.Builder xmppErrorBuilder
= XMPPError.from(XMPPError.Condition.not_authorized, exMsg);
throw new XMPPException.XMPPErrorException(null, xmppErrorBuilder.build());
}
return true;
}
private synchronized Registration getRegistrationInfo(XMPPTCPConnection connection)
throws SmackException.NoResponseException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, InterruptedException
{
Registration reg = new Registration();
reg.setTo(connection.getXMPPServiceDomain());
return createPacketCollectorAndSend(connection, reg).nextResultOrThrow();
}
private PacketCollector createPacketCollectorAndSend(XMPPTCPConnection connection, IQ req)
throws SmackException.NotConnectedException, InterruptedException
{
PacketCollector collector = connection.createPacketCollectorAndSend(new StanzaIdFilter(req.getStanzaId()), req);
return collector;
}
bob.zip (4094 Bytes)