AccountManager.deleteAccount() gets me XMPPError 400 (Bad Request)

Hi!

I am using the smack library to construct an instant-messaging solution based on the latest stable jabberd2; administrative parts of that web-based instant messenger (adding/deleting users/roster-entries, changing passwords) are going to be implemented in ColdFusion MX 6.1.

I have successfully managed to create a new accounts, verify whether an account exists and log in to an existing account. When I try to delete an account, I always get XMPPError 400 (Bad Request).

The following snippet is working fine:

connection = createObject(“java”, “org.jivesoftware.smack.XMPPConnection”).init("#jabber_server#");

AccountManager=connection.getAccountManager();

createAccount = AccountManager.createAccount("#sJabLogin#", “#sJabPassw#”);

login = connection.login("#sJabLogin#", “#sJabPassw#”);

A subsequent

deleteAccount = AccountManager.deleteAccount();

always results in that XMPPError 400. So far I have only succeeded in removing an existing account by deleting the account-data from the authreg-table, then stopping and restarting the jabberd2-server. Of course, this procedure is far from fit for production. How would I delete the account using SMACK, so I don’'t need to restart the server?

Kind regards

Markus

Markus,

Last week I was playing with jabberd2 and detected the same problem and found out that jabberd2 wasn’'t implementing the XMPP specification correctly. In order to remove a user account the XMPP protocol specifies that must be the only child element of the tag which is what Smack exactly implements.

The jabberd2 community knows about this problem and created a bug issue. This is the link http://www.jabberstudio.org/projects/jabberd2/bugs/view.php?id=3166. According to the bug comments in jabberd2.0s2 this problem was supposed to be fixed but it seems that it’‘s still there. You could try with the latest CVS code if you want, though, you could encounter other problems since that code hasn’'t been released yet.

Regards,

– Gato

Thank you very much for your reply - so it wasn’‘t stupid me after all. Well, not this time around. Is there some kind of workaround that would allow one to send a customized deleteAccount via raw XML packet to the server? I have read the documentation on org.jivesoftware.smack.packet.Packet, but it’'s a bit of swahili to me, I cannot figure out how to send

<iq type=’‘set’’ to=’‘my.jabber.server’’>

<query xmlns=’‘jabber:iq:register’’>

which, as far as I understand it, would be the jabberd2-way of deleting a user.

Markus,

The XML that you want to send is the actual XML that Smack is sending to remove user accounts. The problem is that jabberd2s2 does not accept that XML as valid even that the XMPP protocol says so.

I haven’'t tried this solution but a possible temporary fix could be to modify Smack in order to send the removal XML packet as jabberd2s2 expects it to be. This means that you will be able to remove user accounts from jabberd2s2 but the XML that you will be sending is not valid and may not work with other servers or even with newest jabberd versions.

Having said that here is a possible modification. Modify the method AccountManager.deleteAccount() so that the username tag will be included in the XML. Replace

Registration reg = new Registration();
    reg.setType(IQ.Type.SET);
    reg.setTo(connection.getHost());

with

Registration reg = new Registration();
    reg.setType(IQ.Type.SET);
    reg.setTo(connection.getHost());
    reg.setUsername("");

Regards,

– Gato

Another option would be to copy the delete method logic into your own class, including the change that Gato suggests. That way you wouldn’'t have to actually modify the Smack code.

Regards,

Matt

Thanks to both of you - I think I might take the middle path and add a new method deleteAccountJd2s2() to the AccountManager-class. That way I can set a compatibility-flag in my application and use the altered method for as long as the bug remains unfixed in jabberd2.

Unfortunately that didn’'t solve the problem; the new method is just as you suggested:

public void deleteAccountJd2s2() throws XMPPException {

if (!connection.isAuthenticated()) {

throw new IllegalStateException(“Must be logged in to delete an account.”);

}

Registration reg = new Registration();

reg.setType(IQ.Type.SET);

reg.setTo(connection.getHost());

reg.setUsername("");

Map attributes = new HashMap();

// To delete an account, we add a single attribute, “remove”, that is blank.

attributes.put(“remove”, “”);

reg.setAttributes(attributes);

PacketFilter filter = new AndFilter(new PacketIDFilter(reg.getPacketID()),

new PacketTypeFilter(IQ.class));

PacketCollector collector = connection.createPacketCollector(filter);

connection.sendPacket(reg);

IQ result = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());

if (result == null) {

throw new XMPPException(“No response from server.”);

}

else if (result.getType() == IQ.Type.ERROR) {

throw new XMPPException(result.getError());

}

}

But I am still getting XMPPError 400 (Bad Request), when I call

AccountManager=connection.getAccountManager();

deleteAccount = AccountManager.deleteAccountJd2s2();

What else could I try?

Markus,

I looked at jabberd2 source code and found the problem. Unfortunately, there is no workaround from Smack that you can do to resolve the problem.

You can choose any of these 2 possibilities to resolve the problem:

  1. Add this new line
ns = nad_find_scoped_namespace(nad, "jabber:iq:register", NULL);

to c2s/authreg.c in the row number 497. You will need to recompile jabberd to take the modification

  1. Download and install the latest jabberd2 source code from their CVS server.

If you need more help in this issue I’'ll recommend posting any question to jabberd mailing lists.

Regards,

– Gato

Happy Happy Joy Joy!

Thank you very much, that did it! I tried CVS before, but didn’'t succeed in compiling it - and anyway, I just wanted this one fix, not a complete (and maybe unstable) version. That was exactly what I wanted, so thank you!

Kind regards,

Markus