Anyone else having problems modifying groups for transports in Spark?

Ok, I was able to remove those Transport buddies by deleting my login information and adding it in thru Spark instead of registering in Openfire.

However, I have a user whose entire MSN contact list is not displaying when he logs into Spark. I’ve had him delete and reregister that transport from Spark, to no avail, and even restarted the openfire service on the server.

Also, I’m seeing issues now with my MSN contacts also, some of the groups I’d created are gone so I can’t move users out of the Unfiled group into them. When I restarted the openfire service, and Spark reconnected the groups all reappeared but my contacts weren’t showing, so I restarted Spark, and then the groups were gone again. They don’t even display when I choose to Show Empty Groups.

Lastly, none of my Yahoo users are showing in my roster, but if I sent a broadcast message, I see some of them listed there. Weird.

M@

notz wrote:

ok, but why you don’t use the pseudo roster table for all transports?

so if i login i get the hole roster (jiveRoster + pseudoRoster). after you got the roster from icq/msn etc. merge it with the local pseudo roster and send only the diffs to the client. same thing roster updates from client.

so you have the option to disable group syncing (i.e. icq) with the real icq world. i think that all jabber user don’t care in which group the buddy is on icq side.

that, will be a much easier way to handle (i think the pyXxx transports have the same handling).

The whole point of a lot of this support is to make it as smooth as possible. If you decide to fire up a real MSN client, I’d like to see you able to mirror your MSN contacts just as you used them with Spark. Pseudo roster is only for services that don’t support bits and pieces. Hell, I’m already having reports come in because using a single group with the Py’s causes a lot of problems. Lots of people are running into size limit caps for example. People often complain about their groups not being mirroed on the legacy service. There’s little reason for me not to use the services own mechanisms. Just needs to be fixed up apparently.

Maenxe wrote:

Ok, I was able to remove those Transport buddies by deleting my login information and adding it in thru Spark instead of registering in Openfire.

However, I have a user whose entire MSN contact list is not displaying when he logs into Spark. I’ve had him delete and reregister that transport from Spark, to no avail, and even restarted the openfire service on the server.

Any debug logs? What MSN client was he using before?

Also, I’m seeing issues now with my MSN contacts also, some of the groups I’d created are gone so I can’t move users out of the Unfiled group into them. When I restarted the openfire service, and Spark reconnected the groups all reappeared but my contacts weren’t showing, so I restarted Spark, and then the groups were gone again. They don’t even display when I choose to Show Empty Groups.

That’s actually something to be fixed in 1.1.1… I found out Openfire was doing something bizarre on me so I’ve countered it. I spoke with Gato about it and until it can be resolved in Openfire itself, I have a workaround. (of course, there’s little reason for me to ever remove the workaround)

Lastly, none of my Yahoo users are showing in my roster, but if I sent a broadcast message, I see some of them listed there. Weird.

Definitely odd. Can you send me some server side debug logs as you log into the Yahoo transport?

Daniel

M@

hmm,

i don’t understood the code completly here but is that line correct (in OSCARSession.java:262)?

if (buddy.getGroupId() == 0 && !grouplist.contains(DEFAULT_AIM_GROUP)) {

or should it be like this:

if (buddy.getGroupId() == 0 && !grouplist.contains(DEFAULT_AIM_GROUP) && !grouplist.contains(DEFAULT_ICQ_GROUP)) {

it seems that this change solves my icq buddy moving problem. i have to dig in further.

one other question:

i tried to change the option that all gateway roster items are stored in db in (BaseTransport.java:1193) and seems to work out of the box.

why i like this behaviour more?

because if want to store the roster offline it’s working also if the roster is not in cache and there is less traffic on login if the roster is not in cache, because i only the roster changes are transferred and not the hole roster, each in one stanza. (if have not enough cache for all users, there are too much of them)

for usage on a mobile client, it is very useful.

do you think, it is possible to add a option therefore?

notz

Hrm. Crap yes, thanks for the patch! (i’m tweaking it a tad but yes, you are correct in that it should be like that) GATE-319 (i am in the middle of trying things right now so I’m going to wait before posting this for real)

it seems that this change solves my icq buddy moving problem. i have to dig in further.

one other question:

i tried to change the option that all gateway roster items are stored in db in (BaseTransport.java:1193) and seems to work out of the box.

why i like this behaviour more?

because if want to store the roster offline it’s working also if the roster is not in cache and there is less traffic on login if the roster is not in cache, because i only the roster changes are transferred and not the hole roster, each in one stanza. (if have not enough cache for all users, there are too much of them)

for usage on a mobile client, it is very useful.

do you think, it is possible to add a option therefore?

GATE-320 =)

notz wrote:

notz

hmm,

i don’t understood the code completly here but is that line correct (in OSCARSession.java:262)?

if (buddy.getGroupId() == 0 && !grouplist.contains(DEFAULT_AIM_GROUP)) {

or should it be like this:

if (buddy.getGroupId() == 0 && !grouplist.contains(DEFAULT_AIM_GROUP) && !grouplist.contains(DEFAULT_ICQ_GROUP)) {

patch to make moving contacts bewteen group working without loose of information & authorization:

/**

  • Synchronizes the list of groups a contact is a member of, updating nicknames in

  • the process.

  • @param contact Screen name/UIN of the contact.

  • @param nickname Nickname of the contact (should not be null)

  • @param grouplist List of groups the contact should be a member of.

*/

public void syncContactGroupsAndNickname(String contact, String nickname, List();

}

if (grouplist.isEmpty()) {

if (getTransport().getType().equals(TransportType.icq)) {

grouplist.add(DEFAULT_ICQ_GROUP);

}

else {

grouplist.add(DEFAULT_AIM_GROUP);

}

}

// TODO: add another step here where we attempt to “move around” contacts instead of just adding and deleting

Log.debug("contact = “contact”, grouplist = "+grouplist);

OSCARBuddy oscarBuddy = null;

try {

oscarBuddy = (OSCARBuddy)getBuddyManager().getBuddy(getTransport().convertIDToJID(contact));

}

catch (NotFoundException e) {

}

Vector freeBuddyItems = new Vector();

if (oscarBuddy != null) {

// Now, lets clean up any groups this contact should no longer be a member of.

for (BuddyItem buddy : oscarBuddy.getBuddyItems()) {

if (buddy.getScreenname().equalsIgnoreCase(contact)) {

if (buddy.getGroupId() == 0 && !grouplist.contains(DEFAULT_AIM_GROUP)) {

// Ok this group is the “main group”, but contact isn’t in it.

Log.debug(“Removing “buddy” from main group”);

freeBuddyItems.add(b uddy);

}

else if (!groups.containsKey(buddy.getGroupId())) {

// Well this is odd, a group we don’t know about? Nuke it.

Log.debug(“Removing “buddy” because of unknown group”);

freeBuddyItems.add(b uddy);

}

else if (!grouplist.contains(groups.get(buddy.getGroupId()).getGroupName())) {

Log.debug(“Removing “buddy” because not in list of groups”);

freeBuddyItems.add(b uddy);

}

else {

if (buddy.getAlias() == null || !buddy.getAlias().equals(nickname)) {

Log.debug( "Updating alias for "+buddy);

buddy.setA lias(nickname);

request(ne w ModifyItemsCmd(buddy.toSsiItem()));

oscarBuddy .tieBuddyItem(buddy, true);

}

}

}

}

}

// First, lets take the known good list of groups and add whatever is missing on the server.

for (String group : grouplist) {

Integer groupId = getGroupIdOrCreateNew(group);

if (isMemberOfGroup(groupId, contact)) {

// Already a member, moving on

continue;

}

Integer newBuddyId = 1;

if (highestBuddyIdPerGroup.containsKey(groupId)) {

newBuddyId = highestBuddyIdPerGroup.get(groupId) + 1;

}

if (freeBuddyItems.size() > 0) { // moving a free buddy

BuddyItem buddy = (BuddyItem)freeBuddyItems.get(0);

BuddyItem newBuddy = new BuddyItem(contact, groupId, newBuddyId, nickname, buddy.getBuddyComment(), buddy.getAlertWhenMask(), buddy.getAlertActionMask(), buddy.getAlertSound(), false, buddy.getExtraTlvs());

request(new DeleteItemsCmd(buddy.toSsiItem()));

oscarBuddy.removeBuddyItem(buddy.getGrou pId(), false);

freeBuddyItems.remove(buddy);

oscarBuddy.tieBuddyItem(newBuddy, false);

request(new CreateItemsCmd(newBuddy.toSsiItem()));

} else { // creating a new buddy

BuddyItem newBuddy = new BuddyItem(contact, groupId, newBuddyId);

newBuddy.setAlias(nickname);

if (oscarBuddy == null) {

getBuddyManager().storeBuddy(o scarBuddy = new OSCARBuddy(getBuddyManager(), newBuddy));

} else {

oscarBuddy.tieBuddyItem(newBud dy, false);

}

request(new CreateItemsCmd(newBuddy.toSsiItem()));

// TODO: translate this

request(new BuddyAuthRequest(contact, “Automated add request on behalf of user.”));

}

}

for (int i=0; i<freeBuddyItems.size(); i++) {

BuddyItem buddy = (BuddyItem)freeBuddyItems.get(i);

request(new DeleteItemsCmd(buddy.toSsiItem()));

oscarBuddy.removeBuddyItem(buddy.getGroupId(), false);

}

}

/code

Wow notz! You’ve really been busy with this! Thank you! GATE-328

BTW, have you signed a contributor agreement with Jive? I don’t really know at what point I have to ask that. =/ I -think- that we’re still good, but wanted to go ahead and ask anyway.

jadestorm wrote:

BTW, have you signed a contributor agreement with Jive? I don’t really know at what point I have to ask that. =/ I -think- that we’re still good, but wanted to go ahead and ask anyway.

no, i never heard about that.

another question perhaps you can help me:

i want to add online status message for icq like pyicq:

that should to the trick in pyicq:

log.msg(“Setting extended status message to "%s"”%status)

self.backMessage = status

packet = struct.pack(

“!HHHbbH”,

0x001d, # H

len(status)+8, # H

0x0002, # H

0x04, # b

len(status)+4, # b

len(status) # H

) + str(status) + struct.pack(“H”,0x0000)

self.sendSNACnr(0x01, 0x1e, packet)

/code

if i implement this in the gateway plugin like that:

request(new SetExtraInfoCmd(new ExtraInfoBlock(ExtraInfoBlock.TYPE_AVAILMSG, ExtraInfoData.getAvailableMessageBlock(verboseStatus))));

/code

it doesn’t work…

2007.08.24 01:53:23 Sending SNAC command: SetExtraInfoCmd: blocks=[ExtraInfoBlock: type=0x2 (TYPE_AVAILMSG), extraData=<ExtraInfoData: flags=0x4 (FLAG_AVAILMSG_PRESENT), data=00 04 6b 68 6b 6a 00 00>]

2007.08.24 01:53:23 OSCAR bos snac packet received: SnacPacketEvent: snacProcessor=ClientSnacProcessor: lastreqid=16, requests: 16, paused=false, snacPacket=SnacPacket type 0x1/0x21, flag1=0x80: 20 bytes (id=3178446837), snacCommand=ExtraInfoAck: blocks=[ExtraInfoBlock: type=0x2 (TYPE_AVAILMSG), extraData=<ExtraInfoData: flags=0x4 (FLAG_AVAILMSG_PRESENT), data=00 04 6b 68 6b 6a 00 00>, ExtraInfoBlock: type=0xd (null), extraData=<ExtraInfoData: flags=0x4 (FLAG_AVAILMSG_PRESENT), data=46 ce 1d c0>] - FlapPacketEvent: flapProcessor=FlapProcessor: seqNum=SeqNum: min=0, max=65535, last(current)=17, flapCommand=SnacFlapCmd: packet=SnacPacket type 0x1/0x21, flag1=0x80: 28 bytes (id=3178446837), flapPacket=FlapPacket (channel=2, seq=8386)

2007.08.24 01:53:23 OSCAR snac packet received: SnacPacketEvent: snacProcessor=ClientSnacProcessor: lastreqid=16, requests: 16, paused=false, snacPacket=SnacPacket type 0x1/0x21, flag1=0x80: 20 bytes (id=3178446837), snacCommand=ExtraInfoAck: blocks=[ExtraInfoBlock: type=0x2 (TYPE_AVAILMSG), extraData=<ExtraInfoData: flags=0x4 (FLAG_AVAILMSG_PRESENT), data=00 04 6b 68 6b 6a 00 00>, ExtraInfoBlock: type=0xd (null), extraData=<ExtraInfoData: flags=0x4 (FLAG_AVAILMSG_PRESENT), data=46 ce 1d c0>] - FlapPacketEvent: flapProcessor=FlapProcessor: seqNum=SeqNum: min=0, max=65535, last(current)=17, flapCommand=SnacFlapCmd: packet=SnacPacket type 0x1/0x21, flag1=0x80: 28 bytes (id=3178446837), flapPacket=FlapPacket (channel=2, seq=8386)

/code

the command seems to go trough, but something have to be wrong. also have tried to set icqstatus and status message in one command, but that result is the same.

i don’t understand was the 0xd block mean.

have you an hint?

notz

Oh man, it’s been a long time since I had to think about that. If I recall correctly, AIM and ICQ use the same mechanism for that. The caveat being that you have to announce yourself as a proper version of ICQ. (which we may actually not be doing, which may be the whole problem)

This site: http://iserverd1.khstu.ru/oscar/ provides a wealth of useful information about the OSCAR protocol. I don’t know off the top of my head though.

The contributor agreement isn’t anything major. I had to sign it to start working on this. Basically it’s just a agreement with Jive that you won’t come back out of the blue and say “you owe me money for those contributions!”. I believe Matt Tucker is who you would have to get in touch with to sign it. (basically if you submit large patches and such I am required to ask you of that to protect Jive) I can faciliate if you are interested.

Regardless, I still think we’re fine at the moment.

notz wrote:

hmm,

i don’t understood the code completly here but is that line correct (in OSCARSession.java:262)?

if (buddy.getGroupId() == 0 && !grouplist.contains(DEFAULT_AIM_GROUP)) {

or should it be like this:

if (buddy.getGroupId() == 0 && !grouplist.contains(DEFAULT_AIM_GROUP) && !grouplist.contains(DEFAULT_ICQ_GROUP)) {

it seems that this change solves my icq buddy moving problem. i have to dig in further.

Hi notz, I looked back over this and remembered why I have it the way I do. The ICQ group is literally a real group, so it’s supposed to be created if it’s not there. That particular line is accounting for AIM’s default group, which is a group with id 0. (ICQ doesn’t use it the same way for some reason) So that line is explicitly looking for the AIM “main group”. So I think it’s actually correct as is. It’s interesting though that it solved your problems. I’m looking over your other patch though.

here, a small change to fix the status message on login. (icq will follow, thank you for the version hint - but i have to test it a bit more)

Index: src/java/org/jivesoftware/openfire/gateway/protocols/msn/MSNSession.java

===================================================================

— src/java/org/jivesoftware/openfire/gateway/protocols/msn/MSNSession.java (revision 8992)

+++ src/java/org/jivesoftware/openfire/gateway/protocols/msn/MSNSession.java (working copy)

@@ -406,8 +406,8 @@

public void updateStatus(PresenceType presenceType, String verboseStatus) {

if (isLoggedIn()) {

try {

  •                   msnMessenger.getOwner().setPersonalMessage(verboseStatus);
    

msnMessenger.getOwner().setStatus(((MSNTransport)getTransport()).convertXMPPSta tusToMSN(presenceType));

  •            msnMessenger.getOwner().setPersonalMessage(verboseStatus);
    

}

catch (IllegalStateException e) {

// // Hrm, not logged in? Lets fix that.

/code

that’s a patch to get icq extra status message working. but it’s still not working in away mode. any hints? the commands are the same as in pyicq.

Index: src/java/org/jivesoftware/openfire/gateway/protocols/oscar/LoginConnection.java

===================================================================

— src/java/org/jivesoftware/openfire/gateway/protocols/oscar/LoginConnection.java (revision 8992)

+++ src/java/org/jivesoftware/openfire/gateway/protocols/oscar/LoginConnection.java (working copy)

@@ -88,14 +88,24 @@

SnacCommand cmd = e.getSnacCommand();

if (cmd instanceof KeyResponse) {

  •        Log.debug("Handling AIM-style auth.");
    
  •        KeyResponse kr = (KeyResponse) cmd;
    
  •        ByteBlock authkey = kr.getKey();
    
  •        ClientVersionInfo version = new ClientVersionInfo(
    
  •        ClientVersionInfo version = null;
    
  •        if (getMainSession().getTransport().getType().equals(TransportType.icq)) {
    
  •            Log.debug("Handling ICQ-style auth.");
    
  •            version = new ClientVersionInfo(
    
  •                    "ICQBasic",
    
  •                    0x010a, 0x0014, 0x0022, 0, 0x0911, 0x0000043d);
    
  •                                           } else {
    
  •            Log.debug("Handling AIM-style auth.");
    
  •            version = new ClientVersionInfo(
    

“AOL Instant Messenger, version 5.5.3415/WIN32”,

-1, 5, 5, 0, 3415, 239);

  •        }
    
  •        KeyResponse kr = (KeyResponse) cmd;
    
  •        ByteBlock authkey = kr.getKey();
    

String pass = getMainSession().getRegistration().getPassword();

if (getMainSession().getTransport().getType().equals(TransportType.icq)) {

if (pass.length() > 8) {

Index: src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java

===================================================================

— src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java (revision 8992)

+++ src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java (working copy)

@@ -30,10 +30,13 @@

import net.kano.joscar.snaccmd.conn.SetExtraInfoCmd;

import net.kano.joscar.snaccmd.loc.SetInfoCmd;

import net.kano.joscar.snaccmd.InfoData;

+import net.kano.joscar.snaccmd.ExtraInfoBlock;

+import net.kano.joscar.snaccmd.ExtraInfoData;

import net.kano.joscar.snaccmd.CapabilityBlock;

import net.kano.joscar.snaccmd.icq.OfflineMsgIcqRequest;

import net.kano.joscar.ssiitem.BuddyItem;

import net.kano.joscar.ssiitem.GroupItem;

+import net.kano.joscar.tlv.MutableTlvChain;

import org.jivesoftware.util.JiveGlobals;

import org.jivesoftware.util.LocaleUtils;

import org.jivesoftware.util.NotFoundException;

@@ -585,7 +610,9 @@

}

else {

request(new SetInfoCmd(InfoData.forAwayMessage(InfoData.NOT_AWAY)));

  •        request(new SetExtraInfoCmd(new ExtraInfoBlock(ExtraInfoBlock.TYPE_AVAILMSG, ExtraInfoData.getAvailableMessageBlock(verboseStatus == null ? "" : verboseStatus))));
    

}

setPresenceAndStatus(presenceType, verboseStatus);

}

/code

Are you certain that ICQ -has- available message support? (just making sure) Have you seen it before? (I don’t appear to have any clients that have support for it)

jadestorm wrote:

Are you certain that ICQ -has- available message support? (just making sure) Have you seen it before? (I don’t appear to have any clients that have support for it)

hmm, is see the buddy status message with openfire and gateway plugin (also with pyicq). but setting the status is only working in pyicq - they send the same message. there have to be a difference in the login process.

Are you able to set the message using pidgin/gaim? That’s always a good place to look to contrast/compare. I know that I am not doing the “old style” authentication (that’s sorta insecure) which is on my list. Who knows, it might be possible that it’s upset about that.

i can set this message with an icq 5.1 client. but i can’t see this message on an 5.1 client. on adiumX (pidgin) i see this status message but setting doesn’t work.

i give miranda a shot tomorrow.

also authorizing/group moving is working for me with adiumX and icq.5.1. i only have to rerequest the authorization one time on icq/adium side.

before it never worked for me.

here is my last modification, which works best (need extra rerequest on icq side and away message not working).

with this version i never lost any contact, group moving always worked, authorize always worked.

Index: src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java

===================================================================

— src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java (revision 8992)

+++ src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java (working copy)

@@ -30,10 +30,13 @@

import net.kano.joscar.snaccmd.conn.SetExtraInfoCmd;

import net.kano.joscar.snaccmd.loc.SetInfoCmd;

import net.kano.joscar.snaccmd.InfoData;

+import net.kano.joscar.snaccmd.ExtraInfoBlock;

+import net.kano.joscar.snaccmd.ExtraInfoData;

import net.kano.joscar.snaccmd.CapabilityBlock;

import net.kano.joscar.snaccmd.icq.OfflineMsgIcqRequest;

import net.kano.joscar.ssiitem.BuddyItem;

import net.kano.joscar.ssiitem.GroupItem;

+import net.kano.joscar.tlv.MutableTlvChain;

import org.jivesoftware.util.JiveGlobals;

import org.jivesoftware.util.LocaleUtils;

import org.jivesoftware.util.NotFoundException;

@@ -56,7 +59,7 @@

  • Yeesh, this is the one I’m most familiar with and yet it’s the ugliest.

  • This needs some housecleaning.

  • @author Daniel Henninger

*/

public class OSCARSession extends TransportSession {

@@ -65,7 +68,7 @@

/**

  • Initialize a new session object for OSCAR

  • *
    
  • *
    
  • @param registration The registration information to use during login.

  • @param jid The JID associated with this session.

  • @param transport The transport that created this session.

@@ -85,7 +88,7 @@

private static final String DEFAULT_AIM_GROUP = " "; // We’re using 3 spaces to indicated main group, invalid in real aim

private static final String DEFAULT_ICQ_GROUP = “General”;

private SeqNum icqSeqNum = new SeqNum(0, Integer.MAX_VALUE);

/**

  • SSI tracking variables.

*/

@@ -222,6 +225,48 @@

}

// TODO: add another step here where we attempt to “move around” contacts instead of just adding and deleting

Log.debug("contact = “contact”, grouplist = "+grouplist);

  •                           OSCARBuddy oscarBuddy = null;
    
  •    try {
    
  •        oscarBuddy = (OSCARBuddy)getBuddyManager().getBuddy(getTransport().convertIDToJID(contact));
    
  •    }
    
  •    catch (NotFoundException e) {
    
  •    }
    
  •    Vector freeBuddyItems = new Vector();
    
  •    if (oscarBuddy != null) {
    
  •                                           // Now, lets clean up any groups this contact should no longer be a member of.
    
  •                                           for (BuddyItem buddy : oscarBuddy.getBuddyItems()) {
    
  •                                                           if (buddy.getScreenname().equalsIgnoreCase(contact)) {
    
  •                                                                           if (buddy.getGroupId() == 0 && !grouplist.contains(DEFAULT_AIM_GROUP)) {
    
  •                                                                            // Ok this group is the "main group", but contact isn't in it.
    
  •                                                                            Log.debug("Removing "*buddy*" from main group");
    
  •                                                                            freeBuddyItems.add(buddy);
    
  •                                                                           }
    
  •                                                                           else if (!groups.containsKey(buddy.getGroupId())) {
    
  •                                                                            // Well this is odd, a group we don't know about?  Nuke it.
    
  •                                                                            Log.debug("Removing "*buddy*" because of unknown group");
    
  •                                                                            freeBuddyItems.add(buddy);
    
  •                                                                           }
    
  •                                                                           else if (!grouplist.contains(groups.get(buddy.getGroupId()).getGroupName())) {
    
  •                                                                            Log.debug("Removing "*buddy*" because not in list of groups");
    
  •                                                                            freeBuddyItems.add(buddy);
    
  •                                                                           }
    
  •                                                                           else {
    
  •                                                                            if (buddy.getAlias() == null || !buddy.getAlias().equals(nickname)) {
    
  •                                                                            Log.debug("Updating alias for "+buddy);
    
  •                                                                            buddy.setAlias(nickname);
    
  •                                                                            request(new ModifyItemsCmd(buddy.toSsiItem()));
    
  •                                                                            oscarBuddy.tieBuddyItem(buddy, true);
    
  •                                                                            }
    
  •                                                                           }
    
  •                                                           }
    
  •                                           }
    
  •                           }
    

// First, lets take the known good list of groups and add whatever is missing on the server.

for (String group : grouplist) {

Integer groupId = getGroupIdOrCreateNew(group);

@@ -235,57 +280,37 @@

newBuddyId = highestBuddyIdPerGroup.get(groupId) + 1;

}

  •        BuddyItem newBuddy = new BuddyItem(contact, groupId, newBuddyId);
    
  •        newBuddy.setAlias(nickname);
    
  •        try {
    
  •            OSCARBuddy oscarBuddy = (OSCARBuddy)getBuddyManager().getBuddy(getTransport().convertIDToJID(contact));
    
  •            oscarBuddy.tieBuddyItem(newBuddy, true);
    
  •        if (freeBuddyItems.size() > 0) { // moving a free buddy
    
  •                   BuddyItem buddy = (BuddyItem)freeBuddyItems.get(0);
    
  •                                                           BuddyItem newBuddy = new BuddyItem(contact, groupId, newBuddyId, nickname, buddy.getBuddyComment(), buddy.getAlertWhenMask(), buddy.getAlertActionMask(), buddy.getAlertSound(), true, buddy.getExtraTlvs());
    
  •                                                           request(new DeleteItemsCmd(buddy.toSsiItem()));
    
  •                                                           oscarBuddy.removeBuddyItem(buddy.getGroupId(), false);
    
  •                                                           freeBuddyItems.remove(buddy);
    
  •                                                           oscarBuddy.tieBuddyItem(newBuddy, false);
    
  •                                                           request(new CreateItemsCmd(newBuddy.toSsiItem()));
    
  •                                           } else { // creating a new buddy
    
  •                                                           BuddyItem newBuddy = new BuddyItem(contact, groupId, newBuddyId, nickname, null, 0, 0, null, true, null);
    
  •                   newBuddy.setAlias(nickname);
    
  •                                                           if (oscarBuddy == null) {
    
  •                                                                           getBuddyManager().storeBuddy(oscarBuddy = new OSCARBuddy(getBuddyManager(), newBuddy));
    
  •                                                           } else {
    
  •                                                                           oscarBuddy.tieBuddyItem(newBuddy, false);
    
  •                                                           }
    
  •                                               request(new CreateItemsCmd(newBuddy.toSsiItem()));
    
  •            // TODO: translate this
    
  •                   request(new BuddyAuthRequest(contact, "Automated add request on behalf of user."));
    

}

  •        catch (NotFoundException e) {
    
  •            getBuddyManager().storeBuddy(new OSCARBuddy(getBuddyManager(), newBuddy));
    
  •        }
    
  •        request(new CreateItemsCmd(newBuddy.toSsiItem()));
    
  •        // TODO: translate this
    
  •        request(new BuddyAuthRequest(contact, "Automated add request on behalf of user."));
    

}

  •    OSCARBuddy oscarBuddy;
    
  •    try {
    
  •        oscarBuddy = (OSCARBuddy)getBuddyManager().getBuddy(getTransport().convertIDToJID(contact));
    
  •    }
    
  •    catch (NotFoundException e) {
    
  •        Log.error("OSCAR: Serious problem (not found in list) while syncing buddy "+contact);
    
  •        return;
    
  •    }
    
  •    // Now, lets clean up any groups this contact should no longer be a member of.
    
  •    for (BuddyItem buddy : oscarBuddy.getBuddyItems()) {
    
  •        if (buddy.getScreenname().equalsIgnoreCase(contact)) {
    
  •            if (buddy.getGroupId() == 0 && !grouplist.contains(DEFAULT_AIM_GROUP)) {
    
  •                // Ok this group is the "main group", but contact isn't in it.
    
  •                Log.debug("Removing "*buddy*" from main group");
    
  •                request(new DeleteItemsCmd(buddy.toSsiItem()));
    
  •                oscarBuddy.removeBuddyItem(buddy.getGroupId(), true);
    
  •            }
    
  •            else if (!groups.containsKey(buddy.getGroupId())) {
    
  •                // Well this is odd, a group we don't know about?  Nuke it.
    
  •                Log.debug("Removing "*buddy*" because of unknown group");
    
  •                request(new DeleteItemsCmd(buddy.toSsiItem()));
    
  •                oscarBuddy.removeBuddyItem(buddy.getGroupId(), true);
    
  •            }
    
  •            else if (!grouplist.contains(groups.get(buddy.getGroupId()).getGroupName())) {
    
  •                Log.debug("Removing "*buddy*" because not in list of groups");
    
  •                request(new DeleteItemsCmd(buddy.toSsiItem()));
    
  •                oscarBuddy.removeBuddyItem(buddy.getGroupId(), true);
    
  •            }
    
  •            else {
    
  •                if (buddy.getAlias() == null || !buddy.getAlias().equals(nickname)) {
    
  •                    Log.debug("Updating alias for "+buddy);
    
  •                    buddy.setAlias(nickname);
    
  •                    request(new ModifyItemsCmd(buddy.toSsiItem()));
    
  •                    oscarBuddy.tieBuddyItem(buddy, true);
    
  •                }
    
  •            }
    
  •        }
    
  •    }
    
  •    for (int i=0; i<freeBuddyItems.size(); i++) {
    
  •                   BuddyItem buddy = (BuddyItem)freeBuddyItems.get(i);
    
  •                   request(new DeleteItemsCmd(buddy.toSsiItem()));
    
  •                                           oscarBuddy.removeBuddyItem(buddy.getGroupId(), false);
    
  •                           }
    

}

/**

@@ -364,7 +389,7 @@

));

}

}

/**

  • @see org.jivesoftware.openfire.gateway.session.TransportSession#sendBuzzNotification (org.xmpp.packet.JID, String)

*/

@@ -571,7 +596,7 @@

*/

public void updateStatus(PresenceType presenceType, String verboseStatus) {

if (getTransport().getType().equals(TransportType.icq)) {

  •        request(new SetExtraInfoCmd(((OSCARTransport)getTransport()).convertXMPPStatusToICQ(presenc eType)));
    
  •                   request(new SetExtraInfoCmd(((OSCARTransport)getTransport()).convertXMPPStatusToICQ(presenc eType)));
    

}

if (presenceType != PresenceType.available && presenceType != PresenceType.chat) {

String awayMsg = LocaleUtils.getLocalizedString(“gateway.oscar.away”, “gateway”);

@@ -585,7 +610,9 @@

}

else {

request(new SetInfoCmd(InfoData.forAwayMessage(InfoData.NOT_AWAY)));

  •                                           request(new SetExtraInfoCmd(new ExtraInfoBlock(ExtraInfoBlock.TYPE_AVAILMSG, ExtraInfoData.getAvailableMessageBlock(verboseStatus == null ? "" : verboseStatus))));
    

}

setPresenceAndStatus(presenceType, verboseStatus);

}

/code

Thanks man =) I’m probably going to do some efficiency tweaks here and there on it before putting it into the plugin, but I’ll make sure to get it into 1.1.2. Great work!

hy,

thank you for commiting my patch, but i my last diff was a important change and also your modification is not working as it should. you can not use the modify command because you always get RESULT_ID_TAKEN back.

2007.08.27 09:49:51 Sending SNAC command: ModifyItemsCmd: 1 items:

2007.08.27 09:49:51 OSCAR bos snac response received: SnacResponseEvent: request=SnacRequest for ModifyItemsCmd: 1 items: : listeners: , responses: null - SnacPacketEvent: snacProcessor=ClientSnacProcessor: lastreqid=15, requests: 15, paused=false, snacPacket=SnacPacket type 0x13/0xe, flag1=0x80: 2 bytes (id=15), snacCommand=SsiDataModAck: results=0xa (RESULT_ID_TAKEN) - FlapPacketEvent: flapProcessor=FlapProcessor: seqNum=SeqNum: min=0, max=65535, last(current)=16, flapCommand=SnacFlapCmd: packet=SnacPacket type 0x13/0xe, flag1=0x80: 10 bytes (id=15), flapPacket=FlapPacket (channel=2, seq=30090)

/code

i merged your last changes and made a diff again:

Index: src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java

===================================================================

— src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java (revision 9006)

+++ src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java (working copy)

@@ -288,16 +288,19 @@

// Moving a freed buddy item

BuddyItem buddy = freeBuddyItems.remove(0);

oscarBuddy.removeBuddyItem(buddy.getGroupId(), false);

  •            request(new DeleteItemsCmd(buddy.toSsiItem()));
    

buddy.setGroupid(groupId);

buddy.setId(newBuddyId);

buddy.setAlias(nickname);

  •            request(new ModifyItemsCmd(buddy.toSsiItem()));
    
  •            buddy.setAwaitingAuth(true);
    
  •            request(new CreateItemsCmd(buddy.toSsiItem()));
    

oscarBuddy.tieBuddyItem(buddy, false);

}

else {

// Creating a new buddy item

BuddyItem newBuddy = new BuddyItem(contact, groupId, newBuddyId);

newBuddy.setAlias(nickname);

  •            newBuddy.setAwaitingAuth(true);
    

request(new CreateItemsCmd(newBuddy.toSsiItem()));

if (oscarBuddy == null) {

oscarBuddy = new OSCARBuddy(getBuddyManager(), newBuddy);

/code

so no buddy get lost, but you need to reauth the buddies if the have turned on that autorisation is required.

normaly, whe should not set “buddy.setAwaitingAuth(true);” on moving. but if i not set this, my buddy always got deleted (RESULT_ICQ_AUTH_REQUIRED - and the entry is not storred - pidgin gets RESULT_SUCCESS).

i sniffed the packets from pidgin and the gateway plugin. both sends the same packets, but pidgin always waits for the ack to send the next modification. the gateway plugins sends all modifications and gets afterwards the response. i don’t understand your pendingSnac code, but i think it should handle this or? (then it seems not to work correct).

notz wrote:

hy,

thank you for commiting my patch, but i my last diff was a important change and also your modification is not working as it should. you can not use the modify command because you always get RESULT_ID_TAKEN back.

2007.08.27 09:49:51 Sending SNAC command: ModifyItemsCmd: 1 items:

2007.08.27 09:49:51 OSCAR bos snac response received: SnacResponseEvent: request=SnacRequest for ModifyItemsCmd: 1 items: : listeners: , responses: null - SnacPacketEvent: snacProcessor=ClientSnacProcessor: lastreqid=15, requests: 15, paused=false, snacPacket=SnacPacket type 0x13/0xe, flag1=0x80: 2 bytes (id=15), snacCommand=SsiDataModAck: results=0xa (RESULT_ID_TAKEN) - FlapPacketEvent: flapProcessor=FlapProcessor: seqNum=SeqNum: min=0, max=65535, last(current)=16, flapCommand=SnacFlapCmd: packet=SnacPacket type 0x13/0xe, flag1=0x80: 10 bytes (id=15), flapPacket=FlapPacket (channel=2, seq=30090)

/code

Result ID taken sounds like that modifications to the buddy item itself aren’t doing what they’re supposed to. And you know what, I think I know why. (in other words, modify -should- work just fine, it looks like I’m just not doing it right, so to speak)

i merged your last changes and made a diff again:

Index: src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java

===================================================================

— src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java (revision 9006)

+++ src/java/org/jivesoftware/openfire/gateway/protocols/oscar/OSCARSession.java (working copy)

@@ -288,16 +288,19 @@

// Moving a freed buddy item

BuddyItem buddy = freeBuddyItems.remove(0);

oscarBuddy.removeBuddyItem(buddy.getGroupId(), false);

  •            request(new DeleteItemsCmd(buddy.toSsiItem()));
    

buddy.setGroupid(groupId);

buddy.setId(newBuddyId);

buddy.setAlias(nickname);

  •            request(new ModifyItemsCmd(buddy.toSsiItem()));
    
  •            buddy.setAwaitingAuth(true);
    
  •            request(new CreateItemsCmd(buddy.toSsiItem()));
    

oscarBuddy.tieBuddyItem(buddy, false);

}

else {

// Creating a new buddy item

BuddyItem newBuddy = new BuddyItem(contact, groupId, newBuddyId);

newBuddy.setAlias(nickname);

  •            newBuddy.setAwaitingAuth(true);
    

request(new CreateItemsCmd(newBuddy.toSsiItem()));

if (oscarBuddy == null) {

oscarBuddy = new OSCARBuddy(getBuddyManager(), newBuddy);

/code

so no buddy get lost, but you need to reauth the buddies if the have turned on that autorisation is required.

normaly, whe should not set “buddy.setAwaitingAuth(true);” on moving. but if i not set this, my buddy always got deleted (RESULT_ICQ_AUTH_REQUIRED - and the entry is not storred - pidgin gets RESULT_SUCCESS).

Which makes sense since you aren’t modifying, you are deleting and then adding. If we can modify, we don’t need the awaiting auth. (well, except for a brand new item) I think we only have to set it when we’re dealing with ICQ as well. (note that we have to compensate for AIM and ICQ differences in some cases)

i sniffed the packets from pidgin and the gateway plugin. both sends the same packets, but pidgin always waits for the ack to send the next modification. the gateway plugins sends all modifications and gets afterwards the response. i don’t understand your pendingSnac code, but i think it should handle this or? (then it seems not to work correct).

I’d sniffed a couple others in the past (like AIM) and actually have seen them spew all of the changes in one fell swoop without waiting for responses. So there is a precedent for that behavior at least. =) I’m not worried about waiting on the responses right now. Let me do some tweaks and see what I can find.

Daniel

jadestorm wrote:

I’d sniffed a couple others in the past (like AIM) and actually have seen them spew all of the changes in one fell swoop without waiting for responses. So there is a precedent for that behavior at least. =) I’m not worried about waiting on the responses right now. Let me do some tweaks and see what I can find.

you are right, tried now the send the commands after receiving the ack, but the result is the same. hmm, so there is no diffrence between pidgin and the gateway plugin in this part.