summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/oscar/liboscar/ssimanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kopete/protocols/oscar/liboscar/ssimanager.cpp')
-rw-r--r--kopete/protocols/oscar/liboscar/ssimanager.cpp658
1 files changed, 658 insertions, 0 deletions
diff --git a/kopete/protocols/oscar/liboscar/ssimanager.cpp b/kopete/protocols/oscar/liboscar/ssimanager.cpp
new file mode 100644
index 00000000..066e93fa
--- /dev/null
+++ b/kopete/protocols/oscar/liboscar/ssimanager.cpp
@@ -0,0 +1,658 @@
+/*
+ Kopete Oscar Protocol
+ ssimanager.cpp - SSI management
+
+ Copyright ( c ) 2004 Gustavo Pichorim Boiko <gustavo.boiko@kdemail.net>
+ Copyright ( c ) 2004 Matt Rogers <mattr@kde.org>
+
+ Kopete ( c ) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
+
+ based on ssidata.h and ssidata.cpp ( c ) 2002 Tom Linsky <twl6@po.cwru.edu>
+
+ *************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or ( at your option ) any later version. *
+ * *
+ *************************************************************************
+*/
+
+#include "ssimanager.h"
+#include <kdebug.h>
+#include "oscarutils.h"
+
+// -------------------------------------------------------------------
+
+class SSIManagerPrivate
+{
+public:
+ QValueList<Oscar::SSI> SSIList;
+ QValueList<WORD> groupIdList;
+ QValueList<WORD> itemIdList;
+ bool complete;
+ DWORD lastModTime;
+ WORD maxContacts;
+ WORD maxGroups;
+ WORD maxVisible;
+ WORD maxInvisible;
+ WORD maxIgnore;
+ WORD nextContactId;
+ WORD nextGroupId;
+};
+
+SSIManager::SSIManager( QObject *parent, const char *name )
+ : QObject( parent, name )
+{
+ d = new SSIManagerPrivate;
+ d->complete = false;
+ d->lastModTime = 0;
+ d->nextContactId = 0;
+ d->nextGroupId = 0;
+ d->maxContacts = 999;
+ d->maxGroups = 999;
+ d->maxIgnore = 999;
+ d->maxInvisible = 999;
+ d->maxVisible = 999;
+}
+
+
+SSIManager::~SSIManager()
+{
+ clear();
+ delete d;
+}
+
+void SSIManager::clear()
+{
+ //delete all SSIs from the list
+ if ( d->SSIList.count() > 0 )
+ {
+ kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Clearing the SSI list" << endl;
+ QValueList<Oscar::SSI>::iterator it = d->SSIList.begin();
+
+ while ( it != d->SSIList.end() && d->SSIList.count() > 0 )
+ it = d->SSIList.remove( it );
+ };
+
+ d->itemIdList.clear();
+ d->groupIdList.clear();
+ d->complete = false;
+ d->lastModTime = 0;
+ d->nextContactId = 0;
+ d->nextGroupId = 0;
+}
+
+WORD SSIManager::nextContactId()
+{
+ if ( d->nextContactId == 0 )
+ d->nextContactId++;
+
+ d->nextContactId = findFreeId( d->itemIdList, d->nextContactId );
+
+ if ( d->nextContactId == 0xFFFF )
+ {
+ kdWarning(OSCAR_RAW_DEBUG) << k_funcinfo << "No free id!" << endl;
+ return 0xFFFF;
+ }
+
+ if ( d->itemIdList.contains( d->nextContactId ) == 0 )
+ d->itemIdList.append( d->nextContactId );
+
+ return d->nextContactId++;
+}
+
+WORD SSIManager::nextGroupId()
+{
+ if ( d->nextGroupId == 0 )
+ d->nextGroupId++;
+
+ d->nextGroupId = findFreeId( d->groupIdList, d->nextGroupId );
+
+ if ( d->nextGroupId == 0xFFFF )
+ {
+ kdWarning(OSCAR_RAW_DEBUG) << k_funcinfo << "No free group id!" << endl;
+ return 0xFFFF;
+ }
+
+ if ( d->groupIdList.contains( d->nextGroupId ) == 0 )
+ d->groupIdList.append( d->nextGroupId );
+
+ return d->nextGroupId++;
+}
+
+WORD SSIManager::numberOfItems() const
+{
+ return d->SSIList.count();
+}
+
+DWORD SSIManager::lastModificationTime() const
+{
+ return d->lastModTime;
+}
+
+void SSIManager::setLastModificationTime( DWORD lastTime )
+{
+ d->lastModTime = lastTime;
+}
+
+void SSIManager::setParameters( WORD maxContacts, WORD maxGroups, WORD maxVisible, WORD maxInvisible, WORD maxIgnore )
+{
+ //I'm not using k_funcinfo for these debug statements because of
+ //the function's long signature
+ QString funcName = QString::fromLatin1( "[void SSIManager::setParameters] " );
+ kdDebug(OSCAR_RAW_DEBUG) << funcName << "Max number of contacts allowed in SSI: "
+ << maxContacts << endl;
+ kdDebug(OSCAR_RAW_DEBUG) << funcName << "Max number of groups allowed in SSI: "
+ << maxGroups << endl;
+ kdDebug(OSCAR_RAW_DEBUG) << funcName << "Max number of contacts allowed on visible list: "
+ << maxVisible << endl;
+ kdDebug(OSCAR_RAW_DEBUG) << funcName << "Max number of contacts allowed on invisible list: "
+ << maxInvisible << endl;
+ kdDebug(OSCAR_RAW_DEBUG) << funcName << "Max number of contacts allowed on ignore list: "
+ << maxIgnore << endl;
+
+ d->maxContacts = maxContacts;
+ d->maxGroups = maxGroups;
+ d->maxInvisible = maxInvisible;
+ d->maxVisible = maxVisible;
+ d->maxIgnore = maxIgnore;
+}
+
+void SSIManager::loadFromExisting( const QValueList<Oscar::SSI*>& newList )
+{
+ Q_UNUSED( newList );
+ //FIXME: NOT Implemented!
+}
+
+bool SSIManager::hasItem( const Oscar::SSI& item ) const
+{
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ {
+ Oscar::SSI s = ( *it );
+ if ( s == item )
+ return true;
+ }
+
+ return false;
+}
+
+Oscar::SSI SSIManager::findGroup( const QString &group ) const
+{
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ if ( ( *it ).type() == ROSTER_GROUP && (*it ).name().lower() == group.lower() )
+ return ( *it );
+
+
+ return m_dummyItem;
+}
+
+Oscar::SSI SSIManager::findGroup( int groupId ) const
+{
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ if ( ( *it ).type() == ROSTER_GROUP && (*it ).gid() == groupId )
+ return ( *it );
+
+ return m_dummyItem;
+}
+
+Oscar::SSI SSIManager::findContact( const QString &contact, const QString &group ) const
+{
+
+ if ( contact.isNull() || group.isNull() )
+ {
+ kdWarning(OSCAR_RAW_DEBUG) << k_funcinfo <<
+ "Passed NULL name or group string, aborting!" << endl;
+
+ return m_dummyItem;
+ }
+
+ Oscar::SSI gr = findGroup( group ); // find the parent group
+ if ( gr.isValid() )
+ {
+ kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "gr->name= " << gr.name() <<
+ ", gr->gid= " << gr.gid() <<
+ ", gr->bid= " << gr.bid() <<
+ ", gr->type= " << gr.type() << endl;
+
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ {
+ if ( ( *it ).type() == ROSTER_CONTACT && (*it ).name() == contact && (*it ).gid() == gr.gid() )
+ {
+ //we have found our contact
+ kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo <<
+ "Found contact " << contact << " in SSI data" << endl;
+ return ( *it );
+ }
+ }
+ }
+ else
+ {
+ kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo <<
+ "ERROR: Group '" << group << "' not found!" << endl;
+ }
+ return m_dummyItem;
+}
+
+Oscar::SSI SSIManager::findContact( const QString &contact ) const
+{
+
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ if ( ( *it ).type() == ROSTER_CONTACT && (*it ).name() == contact )
+ return ( *it );
+
+ return m_dummyItem;
+}
+
+Oscar::SSI SSIManager::findContact( int contactId ) const
+{
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+
+ for ( it = d->SSIList.begin(); it!= listEnd; ++it )
+ if ( ( *it ).type() == ROSTER_CONTACT && ( *it ).bid() == contactId )
+ return ( *it );
+
+ return m_dummyItem;
+}
+
+Oscar::SSI SSIManager::findItemForIcon( QByteArray iconHash ) const
+{
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+
+ for ( it = d->SSIList.begin(); it!= listEnd; ++it )
+ {
+ if ( ( *it ).type() == ROSTER_BUDDYICONS )
+ {
+ TLV t = Oscar::findTLV( ( *it ).tlvList(), 0x00D5 );
+ Buffer b(t.data);
+ b.skipBytes(1); //don't care about flags
+ BYTE iconSize = b.getByte();
+ QByteArray hash( b.getBlock( iconSize ) );
+ if ( hash == iconHash )
+ {
+ Oscar::SSI s = ( *it );
+ return s;
+ }
+ }
+ }
+ return m_dummyItem;
+}
+
+Oscar::SSI SSIManager::findItemForIconByRef( int ref ) const
+{
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+
+ for ( it = d->SSIList.begin(); it!= listEnd; ++it )
+ {
+ if ( ( *it ).type() == ROSTER_BUDDYICONS )
+ {
+ if ( ( *it ).name().toInt() == ref )
+ {
+ Oscar::SSI s = ( *it );
+ return s;
+ }
+ }
+ }
+ return m_dummyItem;
+}
+
+Oscar::SSI SSIManager::findItem( const QString &contact, int type ) const
+{
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+
+ for ( it = d->SSIList.begin(); it!= listEnd; ++it )
+ if ( ( *it ).type() == type && ( *it ).name() == contact )
+ return ( *it );
+
+ return m_dummyItem;
+}
+
+QValueList<Oscar::SSI> SSIManager::groupList() const
+{
+ QValueList<Oscar::SSI> list;
+
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ if ( ( *it ).type() == ROSTER_GROUP )
+ list.append( ( *it ) );
+
+ return list;
+}
+
+QValueList<Oscar::SSI> SSIManager::contactList() const
+{
+ QValueList<Oscar::SSI> list;
+
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ if ( ( *it ).type() == ROSTER_CONTACT )
+ list.append( ( *it ) );
+
+ return list;
+}
+
+QValueList<Oscar::SSI> SSIManager::visibleList() const
+{
+ QValueList<Oscar::SSI> list;
+
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ if ( ( *it ).type() == ROSTER_VISIBLE )
+ list.append( ( *it ) );
+
+ return list;
+}
+
+QValueList<Oscar::SSI> SSIManager::invisibleList() const
+{
+ QValueList<Oscar::SSI> list;
+
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ if ( ( *it ).type() == ROSTER_INVISIBLE )
+ list.append( ( *it ) );
+
+ return list;
+}
+
+QValueList<Oscar::SSI> SSIManager::contactsFromGroup( const QString &group ) const
+{
+ QValueList<Oscar::SSI> list;
+
+ Oscar::SSI gr = findGroup( group );
+ if ( gr.isValid() )
+ {
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ if ( ( *it ).type() == ROSTER_CONTACT && (*it ).gid() == gr.gid() )
+ list.append( ( *it ) );
+ }
+ return list;
+}
+
+QValueList<Oscar::SSI> SSIManager::contactsFromGroup( int groupId ) const
+{
+ QValueList<Oscar::SSI> list;
+
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ if ( ( *it ).type() == ROSTER_CONTACT && (*it ).gid() == groupId )
+ list.append( ( *it ) );
+
+ return list;
+}
+
+Oscar::SSI SSIManager::visibilityItem() const
+{
+ Oscar::SSI item = m_dummyItem;
+ QValueList<Oscar::SSI>::const_iterator it, listEnd = d->SSIList.end();
+ for ( it = d->SSIList.begin(); it != listEnd; ++it )
+ {
+ if ( ( *it ).type() == 0x0004 )
+ {
+ kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Found visibility setting" << endl;
+ item = ( *it );
+ return item;
+ }
+ }
+
+ return item;
+}
+
+void SSIManager::setListComplete( bool complete )
+{
+ d->complete = complete;
+}
+
+bool SSIManager::listComplete() const
+{
+ return d->complete;
+}
+
+bool SSIManager::newGroup( const Oscar::SSI& group )
+{
+ //trying to find the group by its ID
+ QValueList<Oscar::SSI>::iterator it, listEnd = d->SSIList.end();
+ if ( findGroup( group.name() ).isValid() )
+ return false;
+
+ if ( !group.name().isEmpty() ) //avoid the group with gid 0 and bid 0
+ { // the group is really new
+ kdDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Adding group '" << group.name() << "' to SSI list" << endl;
+
+ d->SSIList.append( group );
+ addID( group );
+ emit groupAdded( group );
+ return true;
+ }
+ return false;
+}
+
+bool SSIManager::updateGroup( const Oscar::SSI& group )
+{
+ Oscar::SSI oldGroup = findGroup( group.name() );
+
+ if ( oldGroup.isValid() )
+ {
+ removeID( oldGroup );
+ d->SSIList.remove( oldGroup );
+ }
+
+ 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 '" << group.name() << "' in SSI list" << endl;
+ d->SSIList.append( group );
+ addID( group );
+ emit groupUpdated( group );
+
+ return true;
+}
+
+bool SSIManager::removeGroup( const Oscar::SSI& group )
+{
+ QString groupName = group.name();
+ kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Removing group " << group.name() << endl;
+ int remcount = d->SSIList.remove( group );
+ removeID( group );
+
+ if ( remcount == 0 )
+ {
+ kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "No groups removed" << endl;
+ return false;
+ }
+
+ emit groupRemoved( groupName );
+ return true;
+}
+
+bool SSIManager::removeGroup( const QString &group )
+{
+ Oscar::SSI gr = findGroup( group );
+
+ if ( gr.isValid() && removeGroup( gr ) )
+ {
+ return true;
+ }
+ else
+ kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Group " << group << " not found." << endl;
+
+ return false;
+}
+
+bool SSIManager::newContact( const Oscar::SSI& contact )
+{
+ if ( d->SSIList.findIndex( contact ) == -1 )
+ {
+ kdDebug( OSCAR_RAW_DEBUG ) << k_funcinfo << "Adding contact '" << contact.name() << "' to SSI list" << endl;
+ addID( contact );
+ d->SSIList.append( contact );
+ emit contactAdded( contact );
+ }
+ else
+ return false;
+ return true;
+}
+
+bool SSIManager::updateContact( const Oscar::SSI& contact )
+{
+ Oscar::SSI oldContact = findContact( contact.name() );
+
+ if ( oldContact.isValid() )
+ {
+ removeID( oldContact );
+ d->SSIList.remove( oldContact );
+ }
+
+ 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 );
+
+ return true;
+}
+
+bool SSIManager::removeContact( const Oscar::SSI& contact )
+{
+ QString contactName = contact.name();
+ int remcount = d->SSIList.remove( contact );
+ removeID( contact );
+
+ if ( remcount == 0 )
+ {
+ kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "No contacts were removed." << endl;
+ return false;
+ }
+
+ emit contactRemoved( contactName );
+ return true;
+}
+
+bool SSIManager::removeContact( const QString &contact )
+{
+ Oscar::SSI ct = findContact( contact );
+
+ if ( ct.isValid() && removeContact( ct ) )
+ return true;
+ else
+ kdDebug(OSCAR_RAW_DEBUG) << k_funcinfo << "Contact " << contact << " not found." << endl;
+
+ return false;
+}
+
+bool SSIManager::newItem( const Oscar::SSI& item )
+{
+ 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 )
+{
+ 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;
+}
+
+void SSIManager::addID( const Oscar::SSI& item )
+{
+ if ( item.type() == ROSTER_GROUP )
+ {
+ if ( d->groupIdList.contains( item.gid() ) == 0 )
+ d->groupIdList.append( item.gid() );
+ }
+ else
+ {
+ if ( d->itemIdList.contains( item.bid() ) == 0 )
+ d->itemIdList.append( item.bid() );
+ }
+}
+
+void SSIManager::removeID( const Oscar::SSI& item )
+{
+ if ( item.type() == ROSTER_GROUP )
+ {
+ d->groupIdList.remove( item.gid() );
+
+ if ( d->nextGroupId > item.gid() )
+ d->nextGroupId = item.gid();
+ }
+ else
+ {
+ d->itemIdList.remove( item.bid() );
+
+ if ( d->nextContactId > item.bid() )
+ d->nextContactId = item.bid();
+ }
+}
+
+WORD SSIManager::findFreeId( const QValueList<WORD>& idList, WORD fromId ) const
+{
+ for ( WORD id = fromId; id < 0x8000; id++ )
+ {
+ if ( idList.contains( id ) == 0 )
+ return id;
+ }
+
+ return 0xFFFF;
+}
+
+#include "ssimanager.moc"
+
+//kate: tab-width 4; indent-mode csands;