Bug 133950 - adding users to visible/invisible list does not work
Summary: adding users to visible/invisible list does not work
Status: REPORTED
Alias: None
Product: kopete
Classification: Unclassified
Component: ICQ and AIM Plugins (show other bugs)
Version: unspecified
Platform: unspecified Linux
: NOR normal with 20 votes (vote)
Target Milestone: ---
Assignee: Kopete Developers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-09-12 10:59 UTC by Tobias Rausch
Modified: 2018-11-17 04:52 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
Prints more debug info (567 bytes, patch)
2007-04-07 18:50 UTC, Roman Jarosz
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Rausch 2006-09-12 10:59:24 UTC
Version:           0.12.1 (using KDE 3.5.2, Kubuntu Package 4:3.5.2-0ubuntu18.1 dapper)
Compiler:          Target: i486-linux-gnu
OS:                Linux (i686) release 2.6.15-26-386

The visible/invisible list for the ICQ protocol does not work.
If you add/remove a user to/from the lists and click OK, he is still in the list!
Same happens when you try it via right-click -> "Always visible for"/"Always invisible for"
Comment 1 morhekil 2006-09-12 20:55:55 UTC
Confirming the bug for Kopete 0.12.2 compiled from svn, KDE 3.5.4 on Gentoo. Though in my case it seems that the action works for some contacts and doesn't work for others.
Also switching to another ICQ client (SIM in my case) and making changes in the lists there also correctly changes visible/invisible lists in Kopete.
Comment 2 benedict 2006-11-20 13:40:00 UTC
Same problem on Gentoo, 

Qt: 3.3.6
KDE: 3.5.5
Kopete: 0.12.3
Comment 3 Roman Jarosz 2006-11-20 20:07:33 UTC
I can't reproduce it, can you provide more info?
Does it work when you remove and add that contact to Kopete list again? Maybe you can send me one icq number that doesn't work so I can test it.

Tobias: you are using Kopete 0.12.1 so you maybe suffering from bug 104243.

Thanks
Comment 4 morhekil 2006-11-21 16:05:38 UTC
Doesn't work with ANY contact here. I can add the contact to my visible list using another IM (tried with SIM, in my case) and it will appear in visible list later in Kopete. I can remove that contact from the list in Kopete, but I can not add it back (and I can't add any other contact too).
The same is true for the contacts initially added to my contacts list with Kopete - can't be added to the visible list.
Comment 5 benedict 2006-11-21 16:25:25 UTC
After removing/adding contact it's start to work, and still working ..
Comment 6 Roman Jarosz 2006-11-21 16:38:15 UTC
Oleg: please run Kopete from console and tell me if you see there "No free id!" or "No free group id!" when you add somebody to in/visible list.

Also console log of Kopete compiled with debug enabled would be helpful.

Thanks.
Comment 7 morhekil 2006-11-21 16:54:36 UTC
Hm, seems that after some messing with the contact list (adding/removing contacts, setting visible/invisible statuses, etc) things start to work. Not sure what was the reason but I can't confirm initial bugreport right now. I'll check the log if the problem reappear.
Comment 8 Arthur Murauskas 2006-12-20 13:42:27 UTC
Having same thing with Yahoo accounts.
Comment 9 Alberto Gonzalez 2007-01-28 21:33:44 UTC
I found this bug too, and it does seem to be related to how much space you have available to allocate users into one list or the other (visible or invisible).

Right now, for example, I can have 1 contact in my visible list and 2 in my invisible list. If I try to add more, it doesn't work. If I remove one, then I can add another one, etc... If I log with Licq and add some contacts to both lists, then I log back with Kopete and I can remove them and add them back (the same or others, but not more than the number I added with Licq).

I'm using KDE 3.5.6 and Kopete 12.3.
Comment 10 Roman Jarosz 2007-03-22 01:10:45 UTC
SVN commit 645234 by rjarosz:

Update our local Server Side Info correctly.
Fix authorization status in ICQ.

Fix bug 133950: adding users to visible/invisible list does not work
Please test it because I can't reproduce it.

BUG: 133950



 M  +23 -1     liboscar/client.cpp  
 M  +0 -9      liboscar/ssiauthtask.cpp  
 M  +62 -27    liboscar/ssimanager.cpp  
 M  +3 -2      liboscar/ssimanager.h  
 M  +116 -12   liboscar/ssimodifytask.cpp  
 M  +12 -1     liboscar/ssimodifytask.h  
 M  +1 -1      oscarcontact.cpp  


--- branches/KDE/3.5/kdenetwork/kopete/protocols/oscar/liboscar/client.cpp #645233:645234
@@ -111,6 +111,7 @@
 	ICQUserInfoRequestTask* icqInfoTask;
 	UserInfoTask* userInfoTask;
 	TypingNotifyTask * typingNotifyTask;
+	SSIModifyTask* ssiModifyTask;
 	//Managers
 	SSIManager* ssiManager;
 	ConnectionHandler connections;
@@ -160,6 +161,7 @@
 	d->userInfoTask = 0L;
 	d->stage = ClientPrivate::StageOne;
 	d->typingNotifyTask = 0L;
+	d->ssiModifyTask = 0L;
 	d->awayMsgRequestTimer = new QTimer();
 	d->codecProvider = &defaultCodecProvider;
 
@@ -619,6 +621,7 @@
 	d->icqInfoTask = new ICQUserInfoRequestTask( c->rootTask() );
 	d->userInfoTask = new UserInfoTask( c->rootTask() );
 	d->typingNotifyTask = new TypingNotifyTask( c->rootTask() );
+	d->ssiModifyTask = new SSIModifyTask( c->rootTask(), true );
 
 	connect( d->onlineNotifier, SIGNAL( userIsOnline( const QString&, const UserDetails& ) ),
 	         this, SIGNAL( receivedUserInfo( const QString&, const UserDetails& ) ) );
@@ -660,6 +663,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->removeGroup( groupName ) )
 		ssimt->go( true );
+	else
+		delete ssimt;
 }
 
 void Client::addGroup( const QString& groupName )
@@ -672,6 +677,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->addGroup( groupName ) )
 		ssimt->go( true );
+	else
+		delete ssimt;
 }
 
 void Client::addContact( const QString& contactName, const QString& groupName )
@@ -684,7 +691,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->addContact( contactName, groupName )  )
 		ssimt->go( true );
-
+	else
+		delete ssimt;
 }
 
 void Client::removeContact( const QString& contactName )
@@ -697,6 +705,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->removeContact( contactName ) )
 		ssimt->go( true );
+	else
+		delete ssimt;
 }
 
 void Client::renameGroup( const QString & oldGroupName, const QString & newGroupName )
@@ -709,6 +719,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->renameGroup( oldGroupName, newGroupName ) )
 		ssimt->go( true );
+	else
+		delete ssimt;
 }
 
 void Client::modifySSIItem( const Oscar::SSI& oldItem, const Oscar::SSI& newItem )
@@ -730,14 +742,20 @@
 	case 0:
 		if ( ssimt->modifyItem( oldItem, newItem ) )
 			ssimt->go( true );
+		else
+			delete ssimt;
 		break;
 	case 1:
 		if ( ssimt->addItem( newItem ) )
 			ssimt->go( true );
+		else
+			delete ssimt;
 		break;
 	case 2:
 		if ( ssimt->removeItem( oldItem ) )
 			ssimt->go( true );
+		else
+			delete ssimt;
 		break;
 	}
 }
@@ -753,6 +771,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->changeGroup( contact, newGroupName ) )
 		ssimt->go( true );
+	else
+		delete ssimt;
 }
 
 void Client::requestFullInfo( const QString& contactId )
@@ -1306,6 +1326,7 @@
 	delete d->icqInfoTask;
 	delete d->userInfoTask;
 	delete d->typingNotifyTask;
+	delete d->ssiModifyTask;
 
 	d->errorTask = 0;
 	d->onlineNotifier = 0;
@@ -1315,6 +1336,7 @@
 	d->icqInfoTask = 0;
 	d->userInfoTask = 0;
 	d->typingNotifyTask = 0;
+	d->ssiModifyTask = 0;
 }
 
 bool Client::hasIconConnection( ) const
--- branches/KDE/3.5/kdenetwork/kopete/protocols/oscar/liboscar/ssiauthtask.cpp #645233:645234
@@ -112,10 +112,6 @@
 	
 	Transfer* t = createTransfer( f, s, buf );
 	send( t );
-	
-	Oscar::SSI contact = m_manager->findContact( uin );
-	if ( contact )
-		contact.setWaitingAuth( true );
 }
 
 void SSIAuthTask::sendAuthReply( const QString& uin, const QString& reason, bool auth )
@@ -175,11 +171,6 @@
 		kdDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Authorization request declined by " << uin << endl;
 		
 	kdDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Reason: " << reason << endl;
-	
-	Oscar::SSI sender = m_manager->findContact( uin );
-	if ( sender )
-		sender.setWaitingAuth( false );
-		
 	emit authReplied( uin, reason, accepted );
 }
 
--- branches/KDE/3.5/kdenetwork/kopete/protocols/oscar/liboscar/ssimanager.cpp #645233:645234
@@ -439,26 +439,27 @@
 	return false;
 }
 
-bool SSIManager::updateGroup( const Oscar::SSI& oldGroup, const Oscar::SSI& newGroup )
+bool SSIManager::updateGroup( const Oscar::SSI& group )
 {
-	removeID( oldGroup );
-	if ( d->SSIList.remove( oldGroup ) == 0 )
+	Oscar::SSI oldGroup = findGroup( group.name() );
+
+	if ( oldGroup.isValid() )
 	{
-		kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "No group were removed." << endl;
-		return false;
+		removeID( oldGroup );
+		d->SSIList.remove( oldGroup );
 	}
-	
-	if ( d->SSIList.findIndex( newGroup ) != -1 )
+
+	if ( d->SSIList.findIndex( group ) != -1 )
 	{
 		kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "New group is already in list." << endl;
 		return false;
 	}
-	
-	kdDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Updating group '" << newGroup.name() << "' in SSI list" << endl;
-	d->SSIList.append( newGroup );
-	addID( newGroup );
-	emit groupUpdated( newGroup );
-	
+
+	kdDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Updating group '" << group.name() << "' in SSI list" << endl;
+	d->SSIList.append( group );
+	addID( group );
+	emit groupUpdated( group );
+
 	return true;
 }
 
@@ -507,26 +508,27 @@
 	return true;
 }
 
-bool SSIManager::updateContact( const Oscar::SSI& oldContact, const Oscar::SSI& newContact )
+bool SSIManager::updateContact( const Oscar::SSI& contact )
 {
-	removeID( oldContact );
-	if ( d->SSIList.remove( oldContact ) == 0 )
+	Oscar::SSI oldContact = findContact( contact.name() );
+
+	if ( oldContact.isValid() )
 	{
-		kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "No contacts were removed." << endl;
-		return false;
+		removeID( oldContact );
+		d->SSIList.remove( oldContact );
 	}
-	
-	if ( d->SSIList.findIndex( newContact ) != -1 )
+
+	if ( d->SSIList.findIndex( contact ) != -1 )
 	{
 		kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "New contact is already in list." << endl;
 		return false;
 	}
+
+	kdDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Updating contact '" << contact.name() << "' in SSI list" << endl;
+	addID( contact );
+	d->SSIList.append( contact );
+	emit contactUpdated( contact );
 	
-	kdDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Updating contact '" << newContact.name() << "' in SSI list" << endl;
-	addID( newContact );
-	d->SSIList.append( newContact );
-	emit contactUpdated( newContact );
-	
 	return true;
 }
 
@@ -560,17 +562,50 @@
 
 bool SSIManager::newItem( const Oscar::SSI& item )
 {
-	//no error checking for now
+	if ( d->SSIList.findIndex( item ) != -1 )
+	{
+		kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Item is already in list." << endl;
+		return false;
+	}
+
 	kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Adding item " << item.toString() << endl;
 	d->SSIList.append( item );
 	addID( item );
 	return true;
 }
 
+bool SSIManager::updateItem( const Oscar::SSI& item )
+{
+	Oscar::SSI oldItem = findItem( item.name(), item.type() );
+
+	if ( oldItem.isValid() )
+	{
+		removeID( oldItem );
+		d->SSIList.remove( oldItem );
+	}
+
+	if ( d->SSIList.findIndex( item ) != -1 )
+	{
+		kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "New item is already in list." << endl;
+		return false;
+	}
+
+	kdDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Updating item in SSI list" << endl;
+	addID( item );
+	d->SSIList.append( item );
+	return true;
+}
+
 bool SSIManager::removeItem( const Oscar::SSI& item )
 {
-	d->SSIList.remove( item );
+	int remcount = d->SSIList.remove( item );
 	removeID( item );
+
+	if ( remcount == 0 )
+	{
+		kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "No items were removed." << endl;
+		return false;
+	}
 	
 	return true;
 }
--- branches/KDE/3.5/kdenetwork/kopete/protocols/oscar/liboscar/ssimanager.h #645233:645234
@@ -104,16 +104,17 @@
 
 public slots:
 	bool newGroup( const Oscar::SSI& group );
-	bool updateGroup( const Oscar::SSI& oldGroup, const Oscar::SSI& newGroup );
+	bool updateGroup( const Oscar::SSI& group );
 	bool removeGroup( const Oscar::SSI& group );
 	bool removeGroup( const QString& group );
 
 	bool newContact( const Oscar::SSI& contact );
-	bool updateContact( const Oscar::SSI& oldContact, const Oscar::SSI& newContact );
+	bool updateContact( const Oscar::SSI& contact );
 	bool removeContact( const Oscar::SSI& contact );
 	bool removeContact( const QString& contact );
 	
 	bool newItem( const Oscar::SSI& item );
+	bool updateItem( const Oscar::SSI& item );
 	bool removeItem( const Oscar::SSI& item );
 
 	void addID( const Oscar::SSI& item );
--- branches/KDE/3.5/kdenetwork/kopete/protocols/oscar/liboscar/ssimodifytask.cpp #645233:645234
@@ -28,9 +28,10 @@
 #include "transfer.h"
 
 
-SSIModifyTask::SSIModifyTask( Task* parent ) : Task( parent )
+SSIModifyTask::SSIModifyTask( Task* parent, bool staticTask ) : Task( parent )
 {
 	m_ssiManager = parent->client()->ssiManager();
+	m_static = staticTask;
 	m_opType = NoType;
 	m_opSubject = NoSubject;
 	m_id = 0;
@@ -50,9 +51,22 @@
 {
 	if ( forMe( transfer ) )
 	{
-		setTransfer( transfer );
-		handleSSIAck();
-		setTransfer( 0 );
+		SnacTransfer* st = dynamic_cast<SnacTransfer*>( transfer );
+		if ( st )
+		{
+			setTransfer( transfer );
+			
+			if ( st->snacSubtype() == 0x0008 )
+				handleSSIAdd();
+			else if ( st->snacSubtype() == 0x0009 )
+				handleSSIUpdate();
+			else if ( st->snacSubtype() == 0x000A )
+				handleSSIRemove();
+			else if ( st->snacSubtype() == 0x000E )
+				handleSSIAck();
+			
+			setTransfer( 0 );
+		}
 		return true;
 	}
 	else
@@ -201,11 +215,23 @@
 	const SnacTransfer* st = dynamic_cast<const SnacTransfer*>( transfer );
 	if ( !st )
 		return false;
+
+	if ( st->snacService() == 0x0013 )
+	{
+		WORD subtype = st->snacSubtype();
+		if ( m_static )
+		{
+			if ( subtype == 0x0008 || subtype == 0x0009 || subtype == 0x000A )
+				return true;
+		}
+		else
+		{
+			if ( subtype == 0x000E && m_id == st->snac().id )
+				return true;
+		}
+	}
 	
-	if ( st->snacService() == 0x0013 && st->snacSubtype() == 0x000E && m_id == st->snac().id )
-		return true;
-	else
-		return false;
+	return false;
 }
 
 void SSIModifyTask::handleSSIAck()
@@ -429,9 +455,9 @@
 		else if ( m_opSubject == Group )
 		{
 			if ( m_opType == Rename )
-				m_ssiManager->updateGroup( m_oldItem, m_newItem );
+				m_ssiManager->updateGroup( m_newItem );
 			else if ( m_opType == Change )
-				m_ssiManager->updateContact( m_oldItem, m_newItem );
+				m_ssiManager->updateContact( m_newItem );
 		}
 		else if ( m_opSubject == NoSubject )
 		{
@@ -443,7 +469,7 @@
 		setSuccess( 0, QString::null );
 		return;
 	}
-	
+
 	if ( m_oldItem.isValid() && !m_newItem )
 	{
 		kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Removing " << m_oldItem.name() << " from SSI manager" << endl;
@@ -469,7 +495,7 @@
 		setSuccess( 0, QString::null );
 		return;
 	}
-	
+
 	setSuccess( 0, QString::null );
 }
 
@@ -530,4 +556,82 @@
 		buffer->addTLV( ( *it ) );
 }
 
+Oscar::SSI SSIModifyTask::getItemFromBuffer( Buffer* buffer ) const
+{
+	QValueList<TLV> tlvList;
+	
+	WORD strlength = buffer->getWord();
+	QString itemName = QString::fromUtf8( buffer->getBlock( strlength ), strlength );
+	WORD groupId = buffer->getWord();
+	WORD itemId = buffer->getWord();
+	WORD itemType = buffer->getWord();
+	WORD tlvLength = buffer->getWord();
+	for ( int i = 0; i < tlvLength; )
+	{
+		TLV t = buffer->getTLV();
+		i += 4;
+		i += t.length;
+		tlvList.append( t );
+	}
+		
+	if ( itemType == ROSTER_CONTACT )
+		itemName = Oscar::normalize( itemName );
+		
+	return Oscar::SSI( itemName, groupId, itemId, itemType, tlvList );
+}
+
+void SSIModifyTask::handleSSIAdd()
+{
+	Buffer* b = transfer()->buffer();
+
+	while ( b->length() > 0 )
+	{
+		Oscar::SSI item = getItemFromBuffer( b );
+		kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Adding " << item.name() << " to SSI manager" << endl;
+
+		if ( item.type() == ROSTER_GROUP )
+			m_ssiManager->newGroup( item );
+		else if ( item.type() == ROSTER_CONTACT )
+			m_ssiManager->newContact( item );
+		else
+			m_ssiManager->newItem( item );
+	}
+}
+
+void SSIModifyTask::handleSSIUpdate()
+{
+	Buffer* b = transfer()->buffer();
+
+	while ( b->length() > 0 )
+	{
+		Oscar::SSI item = getItemFromBuffer( b );
+		kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Updating " << item.name() << " in SSI manager" << endl;
+
+		if ( item.type() == ROSTER_GROUP )
+			m_ssiManager->updateGroup( item );
+		else if ( item.type() == ROSTER_CONTACT )
+			m_ssiManager->updateContact( item );
+		else
+			m_ssiManager->updateItem( item );
+	}
+}
+
+void SSIModifyTask::handleSSIRemove()
+{
+	Buffer* b = transfer()->buffer();
+
+	while ( b->length() > 0 )
+	{
+		Oscar::SSI item = getItemFromBuffer( b );
+		kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Removing " << item.name() << " from SSI manager" << endl;
+
+		if ( item.type() == ROSTER_GROUP )
+			m_ssiManager->removeGroup( item );
+		else if ( item.type() == ROSTER_CONTACT )
+			m_ssiManager->removeContact( item );
+		else
+			m_ssiManager->removeItem( item );
+	}
+}
+
 //kate: tab-width 4; indent-mode csands;
--- branches/KDE/3.5/kdenetwork/kopete/protocols/oscar/liboscar/ssimodifytask.h #645233:645234
@@ -51,7 +51,7 @@
 class SSIModifyTask : public Task
 {
 public:
-    SSIModifyTask(Task* parent);
+    SSIModifyTask( Task* parent, bool staticTask = false );
     ~SSIModifyTask();
 
 	virtual void onGo();
@@ -128,7 +128,17 @@
 	void sendEditEnd();
 	
 	void addItemToBuffer( Oscar::SSI item, Buffer* buffer );
+	Oscar::SSI getItemFromBuffer( Buffer* buffer ) const;
 	
+	//! Handle server request to add item
+	void handleSSIAdd();
+	
+	//! Handle server request to update item
+	void handleSSIUpdate();
+	
+	//! Handle server request to remove item
+	void handleSSIRemove();
+
 private:
 	SSI m_oldItem;
 	SSI m_newItem;
@@ -137,6 +147,7 @@
 	OperationSubject m_opSubject;
 	WORD m_id;
 	SSIManager* m_ssiManager;
+	bool m_static;
 	
 };
 
--- branches/KDE/3.5/kdenetwork/kopete/protocols/oscar/oscarcontact.cpp #645233:645234
@@ -142,7 +142,7 @@
 	if( !metaContact() || metaContact()->isTemporary() )
 		return;
 	
-	if ( flags & Kopete::Contact::MovedBetweenGroup == Kopete::Contact::MovedBetweenGroup )
+	if ( (flags & Kopete::Contact::MovedBetweenGroup) == Kopete::Contact::MovedBetweenGroup )
 	{
 		kdDebug(OSCAR_GEN_DEBUG) << k_funcinfo << "Moving a contact between groups" << endl;
 		SSIManager* ssiManager = mAccount->engine()->ssiManager();
Comment 11 Roman Jarosz 2007-03-22 13:57:12 UTC
SVN commit 645365 by rjarosz:

Forwardport: Update our local Server Side Info correctly.
Fix authorization status in ICQ.

Fix bug 133950: adding users to visible/invisible list does not work
Please test it because I can't reproduce it.

CCBUG: 133950



 M  +23 -1     client.cpp  
 M  +62 -28    contactmanager.cpp  
 M  +3 -2      contactmanager.h  
 M  +0 -9      tasks/ssiauthtask.cpp  
 M  +113 -10   tasks/ssimodifytask.cpp  
 M  +14 -3     tasks/ssimodifytask.h  


--- trunk/KDE/kdenetwork/kopete/protocols/oscar/liboscar/client.cpp #645364:645365
@@ -117,6 +117,7 @@
 	ICQUserInfoRequestTask* icqInfoTask;
 	UserInfoTask* userInfoTask;
 	TypingNotifyTask * typingNotifyTask;
+	SSIModifyTask* ssiModifyTask;
 	//Managers
 	ContactManager* ssiManager;
 	ConnectionHandler connections;
@@ -174,6 +175,7 @@
 	d->userInfoTask = 0L;
 	d->stage = ClientPrivate::StageOne;
 	d->typingNotifyTask = 0L;
+	d->ssiModifyTask = 0L;
 	d->awayMsgRequestTimer = new QTimer();
 	d->codecProvider = &defaultCodecProvider;
 
@@ -711,6 +713,7 @@
 	d->icqInfoTask = new ICQUserInfoRequestTask( c->rootTask() );
 	d->userInfoTask = new UserInfoTask( c->rootTask() );
 	d->typingNotifyTask = new TypingNotifyTask( c->rootTask() );
+	d->ssiModifyTask = new SSIModifyTask( c->rootTask(), true );
 
 	connect( d->onlineNotifier, SIGNAL( userIsOnline( const QString&, const UserDetails& ) ),
 	         this, SIGNAL( receivedUserInfo( const QString&, const UserDetails& ) ) );
@@ -754,6 +757,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->removeGroup( groupName ) )
 		ssimt->go( true );
+	else
+		delete ssimt;
 }
 
 void Client::addGroup( const QString& groupName )
@@ -766,6 +771,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->addGroup( groupName ) )
 		ssimt->go( true );
+	else
+		delete ssimt;
 }
 
 void Client::addContact( const QString& contactName, const QString& groupName )
@@ -778,7 +785,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->addContact( contactName, groupName )  )
 		ssimt->go( true );
-
+	else
+		delete ssimt;
 }
 
 void Client::removeContact( const QString& contactName )
@@ -791,6 +799,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->removeContact( contactName ) )
 		ssimt->go( true );
+	else
+		delete ssimt;
 }
 
 void Client::renameGroup( const QString & oldGroupName, const QString & newGroupName )
@@ -803,6 +813,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->renameGroup( oldGroupName, newGroupName ) )
 		ssimt->go( true );
+	else
+		delete ssimt;
 }
 
 void Client::modifyContactItem( const OContact& oldItem, const OContact& newItem )
@@ -824,14 +836,20 @@
 	case 0:
 		if ( ssimt->modifyItem( oldItem, newItem ) )
 			ssimt->go( true );
+		else
+			delete ssimt;
 		break;
 	case 1:
 		if ( ssimt->addItem( newItem ) )
 			ssimt->go( true );
+		else
+			delete ssimt;
 		break;
 	case 2:
 		if ( ssimt->removeItem( oldItem ) )
 			ssimt->go( true );
+		else
+			delete ssimt;
 		break;
 	}
 }
@@ -847,6 +865,8 @@
 	SSIModifyTask* ssimt = new SSIModifyTask( c->rootTask() );
 	if ( ssimt->changeGroup( contact, newGroupName ) )
 		ssimt->go( true );
+	else
+		delete ssimt;
 }
 
 void Client::requestFullInfo( const QString& contactId )
@@ -1453,6 +1473,7 @@
 	delete d->icqInfoTask;
 	delete d->userInfoTask;
 	delete d->typingNotifyTask;
+	delete d->ssiModifyTask;
 
 	d->errorTask = 0;
 	d->onlineNotifier = 0;
@@ -1462,6 +1483,7 @@
 	d->icqInfoTask = 0;
 	d->userInfoTask = 0;
 	d->typingNotifyTask = 0;
+	d->ssiModifyTask = 0;
 }
 
 bool Client::hasIconConnection( ) const
--- trunk/KDE/kdenetwork/kopete/protocols/oscar/liboscar/contactmanager.cpp #645364:645365
@@ -448,26 +448,26 @@
 	return false;
 }
 
-bool ContactManager::updateGroup( const OContact& oldGroup, const OContact& newGroup )
+bool ContactManager::updateGroup( const OContact& group )
 {
-	removeID( oldGroup );
-	if ( d->contactList.removeAll( oldGroup ) == 0 )
+	OContact oldGroup = findGroup( group.name() );
+
+	if ( oldGroup.isValid() )
 	{
-		kDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "No group were removed." << endl;
-		return false;
+		removeID( oldGroup );
+		d->contactList.removeAll( oldGroup );
 	}
-	
-	if ( d->contactList.contains( newGroup ) )
+
+	if ( d->contactList.contains( group ) )
 	{
 		kDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "New group is already in list." << endl;
 		return false;
 	}
-	
-	kDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Updating group '" << newGroup.name() << "' in SSI list" << endl;
-	addID( newGroup );
-	d->contactList.append( newGroup );
-	emit groupUpdated( newGroup );
-	
+
+	kDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Updating group '" << group.name() << "' in SSI list" << endl;
+	addID( group );
+	d->contactList.append( group );
+	emit groupUpdated( group );
 	return true;
 }
 
@@ -516,26 +516,26 @@
 	return true;
 }
 
-bool ContactManager::updateContact( const OContact& oldContact, const OContact& newContact )
+bool ContactManager::updateContact( const OContact& contact )
 {
-	removeID( oldContact );
-	if ( d->contactList.removeAll( oldContact ) == 0 )
+	OContact oldContact = findContact( contact.name() );
+
+	if ( oldContact.isValid() )
 	{
-		kDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "No contacts were removed." << endl;
-		return false;
+		removeID( oldContact );
+		d->contactList.removeAll( oldContact );
 	}
-	
-	if ( d->contactList.contains( newContact ) )
+
+	if ( d->contactList.contains( contact ) )
 	{
 		kDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "New contact is already in list." << endl;
 		return false;
 	}
-	
-	kDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Updating contact '" << newContact.name() << "' in SSI list" << endl;
-	addID( newContact );
-	d->contactList.append( newContact );
-	emit contactUpdated( newContact );
-	
+
+	kDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Updating contact '" << contact.name() << "' in SSI list" << endl;
+	addID( contact );
+	d->contactList.append( contact );
+	emit contactUpdated( contact );
 	return true;
 }
 
@@ -569,17 +569,51 @@
 
 bool ContactManager::newItem( const OContact& item )
 {
-	//no error checking for now
+	if ( d->contactList.contains( item ) )
+	{
+		kDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Item is already in list." << endl;
+		return false;
+	}
+
 	kDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Adding item " << item.toString() << endl;
 	addID( item );
 	d->contactList.append( item );
 	return true;
 }
 
+bool ContactManager::updateItem( const OContact& item )
+{
+	OContact oldItem = findItem( item.name(), item.type() );
+
+	if ( oldItem.isValid() )
+	{
+		removeID( oldItem );
+		d->contactList.removeAll( oldItem );
+	}
+
+	if ( d->contactList.contains( item ) )
+	{
+		kDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "New item is already in list." << endl;
+		return false;
+	}
+
+	kDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Updating item in SSI list" << endl;
+	addID( item );
+	d->contactList.append( item );
+	return true;
+}
+
 bool ContactManager::removeItem( const OContact& item )
 {
 	removeID( item );
-	d->contactList.removeAll( item );
+	int remcount = d->contactList.removeAll( item );
+
+	if ( remcount == 0 )
+	{
+		kDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "No items were removed." << endl;
+		return false;
+	}
+
 	return true;
 }
 
--- trunk/KDE/kdenetwork/kopete/protocols/oscar/liboscar/contactmanager.h #645364:645365
@@ -105,16 +105,17 @@
 
 public slots:
 	bool newGroup( const OContact& group );
-	bool updateGroup( const OContact& oldGroup, const OContact& newGroup );
+	bool updateGroup( const OContact& group );
 	bool removeGroup( const OContact& group );
 	bool removeGroup( const QString& group );
 
 	bool newContact( const OContact& contact );
-	bool updateContact( const OContact& oldContact, const OContact& newContact );
+	bool updateContact( const OContact& contact );
 	bool removeContact( const OContact& contact );
 	bool removeContact( const QString& contact );
 	
 	bool newItem( const OContact& item );
+	bool updateItem( const OContact& item );
 	bool removeItem( const OContact& item );
 
 	void addID( const OContact& item );
--- trunk/KDE/kdenetwork/kopete/protocols/oscar/liboscar/tasks/ssiauthtask.cpp #645364:645365
@@ -112,10 +112,6 @@
 	
 	Transfer* t = createTransfer( f, s, buf );
 	send( t );
-	
-	OContact contact = m_manager->findContact( uin );
-	if ( contact )
-		contact.setWaitingAuth( true );
 }
 
 void SSIAuthTask::sendAuthReply( const QString& uin, const QString& reason, bool auth )
@@ -175,11 +171,6 @@
 		kDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Authorization request declined by " << uin << endl;
 		
 	kDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Reason: " << reason << endl;
-	
-	OContact sender = m_manager->findContact( uin );
-	if ( sender )
-		sender.setWaitingAuth( false );
-		
 	emit authReplied( uin, reason, accepted );
 }
 
--- trunk/KDE/kdenetwork/kopete/protocols/oscar/liboscar/tasks/ssimodifytask.cpp #645364:645365
@@ -28,9 +28,10 @@
 #include "transfer.h"
 
 
-SSIModifyTask::SSIModifyTask( Task* parent ) : Task( parent )
+SSIModifyTask::SSIModifyTask( Task* parent, bool staticTask ) : Task( parent )
 {
 	m_ssiManager = parent->client()->ssiManager();
+	m_static = staticTask;
 	m_opType = NoType;
 	m_opSubject = NoSubject;
 	m_id = 0;
@@ -50,9 +51,22 @@
 {
 	if ( forMe( transfer ) )
 	{
-		setTransfer( transfer );
-		handleContactAck();
-		setTransfer( 0 );
+		SnacTransfer* st = dynamic_cast<SnacTransfer*>( transfer );
+		if ( st )
+		{
+			setTransfer( transfer );
+
+			if ( st->snacSubtype() == 0x0008 )
+				handleContactAdd();
+			else if ( st->snacSubtype() == 0x0009 )
+				handleContactUpdate();
+			else if ( st->snacSubtype() == 0x000A )
+				handleContactRemove();
+			else if ( st->snacSubtype() == 0x000E )
+				handleContactAck();
+
+			setTransfer( 0 );
+		}
 		return true;
 	}
 	else
@@ -202,10 +216,22 @@
 	if ( !st )
 		return false;
 
-	if ( st->snacService() == 0x0013 && st->snacSubtype() == 0x000E && m_id == st->snac().id )
-		return true;
-	else
-		return false;
+	if ( st->snacService() == 0x0013 )
+	{
+		WORD subtype = st->snacSubtype();
+		if ( m_static )
+		{
+			if ( subtype == 0x0008 || subtype == 0x0009 || subtype == 0x000A )
+				return true;
+		}
+		else
+		{
+			if ( subtype == 0x000E && m_id == st->snac().id )
+				return true;
+		}
+	}
+
+	return false;
 }
 
 void SSIModifyTask::handleContactAck()
@@ -429,9 +455,9 @@
 		else if ( m_opSubject == Group )
 		{
 			if ( m_opType == Rename )
-				m_ssiManager->updateGroup( m_oldItem, m_newItem );
+				m_ssiManager->updateGroup( m_newItem );
 			else if ( m_opType == Change )
-				m_ssiManager->updateContact( m_oldItem, m_newItem );
+				m_ssiManager->updateContact( m_newItem );
 		}
 		else if ( m_opSubject == NoSubject )
 		{
@@ -530,4 +556,81 @@
 		buffer->addTLV( ( *it ) );
 }
 
+OContact SSIModifyTask::getItemFromBuffer( Buffer* buffer ) const
+{
+	QList<TLV> tlvList;
+
+	QString itemName = QString::fromUtf8( buffer->getBSTR() );
+	Oscar::WORD groupId = buffer->getWord();
+	Oscar::WORD itemId = buffer->getWord();
+	Oscar::WORD itemType = buffer->getWord();
+	Oscar::WORD tlvLength = buffer->getWord();
+	for ( int i = 0; i < tlvLength; )
+	{
+		TLV t = buffer->getTLV();
+		i += 4;
+		i += t.length;
+		tlvList.append( t );
+	}
+
+	if ( itemType == ROSTER_CONTACT )
+		itemName = Oscar::normalize( itemName );
+
+	return OContact( itemName, groupId, itemId, itemType, tlvList );
+}
+
+void SSIModifyTask::handleContactAdd()
+{
+	Buffer* b = transfer()->buffer();
+
+	while ( b->bytesAvailable() > 0 )
+	{
+		OContact item = getItemFromBuffer( b );
+		kDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Adding " << item.name() << " to SSI manager" << endl;
+
+		if ( item.type() == ROSTER_GROUP )
+			m_ssiManager->newGroup( item );
+		else if ( item.type() == ROSTER_CONTACT )
+			m_ssiManager->newContact( item );
+		else
+			m_ssiManager->newItem( item );
+	}
+}
+
+void SSIModifyTask::handleContactUpdate()
+{
+	Buffer* b = transfer()->buffer();
+
+	while ( b->bytesAvailable() > 0 )
+	{
+		OContact item = getItemFromBuffer( b );
+		kDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Updating " << item.name() << " in SSI manager" << endl;
+
+		if ( item.type() == ROSTER_GROUP )
+			m_ssiManager->updateGroup( item );
+		else if ( item.type() == ROSTER_CONTACT )
+			m_ssiManager->updateContact( item );
+		else
+			m_ssiManager->updateItem( item );
+	}
+}
+
+void SSIModifyTask::handleContactRemove()
+{
+	Buffer* b = transfer()->buffer();
+
+	while ( b->bytesAvailable() > 0 )
+	{
+		OContact item = getItemFromBuffer( b );
+		kDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Removing " << item.name() << " from SSI manager" << endl;
+
+		if ( item.type() == ROSTER_GROUP )
+			m_ssiManager->removeGroup( item );
+		else if ( item.type() == ROSTER_CONTACT )
+			m_ssiManager->removeContact( item );
+		else
+			m_ssiManager->removeItem( item );
+	}
+}
+
 //kate: tab-width 4; indent-mode csands;
--- trunk/KDE/kdenetwork/kopete/protocols/oscar/liboscar/tasks/ssimodifytask.h #645364:645365
@@ -52,7 +52,7 @@
 class SSIModifyTask : public Task
 {
 public:
-    SSIModifyTask(Task* parent);
+    SSIModifyTask( Task* parent, bool staticTask = false );
     ~SSIModifyTask();
 
 	virtual void onGo();
@@ -129,7 +129,17 @@
 	void sendEditEnd();
 	
 	void addItemToBuffer( OContact item, Buffer* buffer );
-	
+	OContact getItemFromBuffer( Buffer* buffer ) const;
+
+	//! Handle server request to add data
+	void handleContactAdd();
+
+	//! Handle server request to update data
+	void handleContactUpdate();
+
+	//! Handle server request to remove data
+	void handleContactRemove();
+
 private:
 	OContact m_oldItem;
 	OContact m_newItem;
@@ -138,7 +148,8 @@
 	OperationSubject m_opSubject;
 	Oscar::WORD m_id;
 	ContactManager* m_ssiManager;
-	
+	bool m_static;
+
 };
 
 #endif
Comment 12 Alberto Gonzalez 2007-04-06 23:35:11 UTC
I've built kopete from svn today (version 651173) and the problem is not fixed. I still can't add users freely to visible/invisible lists. It is a strange bug not very consistent, you might be able to add one user and then you can't add more. Other times you can add more users... It's strange.

In LICQ it does work correctly, in case anyone can look at how it does it.
Comment 13 Roman Jarosz 2007-04-07 11:12:55 UTC
Alberto: can you compile Kopete with debug enabled and post console log here?

Thanks
Comment 14 Roman Jarosz 2007-04-07 12:04:12 UTC
Can you also tell me which clients did you use before Kopete?

Thanks
Comment 15 Alberto Gonzalez 2007-04-07 15:33:41 UTC
Ok, I've built kpote from svn again (version 651357) with -enable-debug=full.

When adding a user to the invisible list (which results in a failed addition) what I get is:

kopete (oscar - raw protocol): [void Client::setInvisibleTo(const QString&, bool)] Adding XXXXXXXX to invisible list
kopete (oscar - raw protocol): [void Client::modifySSIItem(const Oscar::SSI&, const Oscar::SSI&)] Add/Mod/Del item on server
kopete (oscar - raw protocol): [void SSIModifyTask::sendSSIUpdate()] Adding an item to the SSI list
kopete (oscar - raw protocol): [void CoreProtocol::addIncomingData(const QByteArray&)] Received 26 bytes. 
kopete (oscar - raw protocol): [virtual Transfer* SnacProtocol::parse(const QByteArray&, uint&)] family: 19 subtype: 14 flags: 32768 id: 52085
kopete (oscar - raw protocol): Acknowledgement code is 1
kopete (oscar - raw protocol): [void SSIModifyTask::handleSSIAck()] Unknown acknowledgement code

Before kopete I used the original winicq client and Gaim.
Comment 16 Roman Jarosz 2007-04-07 18:50:41 UTC
Created attachment 20206 [details]
Prints more debug info

Alberto: I'm sorry but I cannot reproduce it and we don't know what
acknowledgement code 1 is :(

If you could apply attached patch (It adds more debug info to oscar), compile
oscar, run Kopete from console and send me a log, it would be great.

I swear I wont be providing your log to anybody else and I will delete it when
I fix this bug or give up.
My email is: kedgedev at centrum dot cz

Steps to compile and run:
cd kopete
patch -p0 < /path/to/ssidebug.diff
cd protocols/oscar/
make install

and run kopete:
kopete --nofork 2>debug.log
the log will be in debug.log.

Thanks
Comment 17 Roman K. 2008-07-07 13:38:00 UTC
I tested it with KDE 4.0.85 (KDE 4.1 >= 20080703) openSUSE packages.
What I did:

1. Add Contacts to Always Visible/Always Invisible list and save.
2. Restart Kopete, the lists had the same contacts that I added before.
3. Remove contacts and save.
4. Restart Kopete, now the list was empty again.

=> I cannot confirm the bug
Comment 18 Alberto Gonzalez 2008-07-07 13:53:35 UTC
I helped Roman Jarosz to debug this problem about a year ago. Apparently, the bug only happens with old accounts where many old contacts have been deleted over time and some kind of limit has been reached. IIRC, each time you delete an old contact it leaves some trace on the server, and once you reach a limit (like 200 or so, can't remember exactly) things act strangely. But with the official ICQ client (Windows) and with Licq (Linux), this problem doesn't happen, so Kopete must be doing something strange.

However, in the end it is a low impact bug: Not only it affects a small number of users, it even has workarounds (like retrying to add/delete contacts to/from the invisible list a few times until they stick the way you want them).
Comment 19 Alexander Ponyatikh 2008-11-01 09:33:37 UTC
I have a similar problem, but not sure if it's related to this bug...

If I select user from the drop-down list, it perfectly adds.
But if I type part of the name (kopete autoselects first match then), contact won't appear in the list.

Qt: 4.4.3
KDE: 4.1.2 (KDE 4.1.2)
Kopete: 0.60.2
Kubuntu: 8.10 x64
Comment 20 Andrew Crouthamel 2018-11-05 03:18:50 UTC
Dear Bug Submitter,

This bug has been stagnant for a long time. Could you help us out and re-test if the bug is valid in the latest version? I am setting the status to NEEDSINFO pending your response, please change the Status back to REPORTED when you respond.

Thank you for helping us make KDE software even better for everyone!
Comment 21 Andrew Crouthamel 2018-11-17 04:52:37 UTC
Dear Bug Submitter,

This is a reminder that this bug has been stagnant for a long time. Could you help us out and re-test if the bug is valid in the latest version? This bug will be moved back to REPORTED Status for manual review later, which may take a while. If you are able to, please lend us a hand.

Thank you for helping us make KDE software even better for everyone!