File indexing completed on 2024-04-21 04:04:42
0001 /* 0002 * jabbercontactpool.cpp 0003 * 0004 * Copyright (c) 2004 by Till Gerken <till@tantalo.net> 0005 * Copyright (c) 2006 by Olivier Goffart <ogoffart at kde.org> 0006 * 0007 * Kopete (c) by the Kopete developers <kopete-devel@kde.org> 0008 * 0009 * ************************************************************************* 0010 * * * 0011 * * This program is free software; you can redistribute it and/or modify * 0012 * * it under the terms of the GNU General Public License as published by * 0013 * * the Free Software Foundation; either either version 2 0014 of the License, or (at your option) any later version.of the License, or * 0015 * * (at your option) any later version. * 0016 * * * 0017 * ************************************************************************* 0018 */ 0019 0020 #include "jabbercontactpool.h" 0021 #include "jabber_protocol_debug.h" 0022 0023 #include <KMessageBox> 0024 #include <kopeteaccountmanager.h> 0025 #include <kopetecontactlist.h> 0026 #include "kopeteuiglobal.h" 0027 #include "kopetemetacontact.h" 0028 0029 #include "jabberprotocol.h" 0030 #include "jabberbasecontact.h" 0031 #include "jabbercontact.h" 0032 #include "jabbergroupcontact.h" 0033 #include "jabbergroupmembercontact.h" 0034 #include "jabberresourcepool.h" 0035 #include "jabberaccount.h" 0036 #include "jabbertransport.h" 0037 0038 JabberContactPool::JabberContactPool ( JabberAccount *account ) 0039 { 0040 0041 mAccount = account; 0042 0043 } 0044 0045 JabberContactPool::~JabberContactPool () 0046 { 0047 qDeleteAll(mPool); 0048 } 0049 0050 JabberContactPoolItem *JabberContactPool::findPoolItem ( const XMPP::RosterItem &contact ) 0051 { 0052 0053 // see if the contact already exists 0054 foreach(JabberContactPoolItem *mContactItem, mPool) 0055 { 0056 if ( mContactItem->contact()->rosterItem().jid().full().toLower() == contact.jid().full().toLower() ) 0057 { 0058 return mContactItem; 0059 } 0060 } 0061 0062 return 0; 0063 0064 } 0065 0066 JabberContact *JabberContactPool::addContact ( const XMPP::RosterItem &contact, Kopete::MetaContact *metaContact, bool dirty ) 0067 { 0068 // see if the contact already exists 0069 JabberContactPoolItem *mContactItem = findPoolItem ( contact ); 0070 if ( mContactItem) 0071 { 0072 qCDebug(JABBER_PROTOCOL_LOG) << "Updating existing contact " << contact.jid().full() << " - " << mContactItem->contact(); 0073 0074 // It exists, update it. 0075 mContactItem->contact()->updateContact ( contact ); 0076 mContactItem->setDirty ( dirty ); 0077 0078 JabberContact *retval = dynamic_cast<JabberContact *>(mContactItem->contact ()); 0079 0080 if ( !retval ) 0081 { 0082 KMessageBox::error ( Kopete::UI::Global::mainWidget (), 0083 "Fatal error in the Jabber contact pool. Please restart Kopete and submit a debug log " 0084 "of your session to http://bugs.kde.org.", 0085 "Fatal Jabber Error" ); 0086 } 0087 0088 return retval; 0089 } 0090 0091 qCDebug(JABBER_PROTOCOL_LOG) << "Adding new contact " << contact.jid().full(); 0092 0093 JabberTransport *transport=0l; 0094 QString legacyId; 0095 //find if the contact should be added to a transport. 0096 if(mAccount->transports().contains(contact.jid().domain())) 0097 { 0098 transport=mAccount->transports()[contact.jid().domain()]; 0099 legacyId=transport->legacyId( contact.jid() ); 0100 } 0101 0102 // create new contact instance and add it to the dictionary 0103 JabberContact *newContact = new JabberContact ( contact, transport ? (Kopete::Account*)transport : (Kopete::Account*)mAccount, metaContact , legacyId ); 0104 JabberContactPoolItem *newContactItem = new JabberContactPoolItem ( newContact ); 0105 connect ( newContact, SIGNAL (contactDestroyed(Kopete::Contact*)), this, SLOT (slotContactDestroyed(Kopete::Contact*)) ); 0106 newContactItem->setDirty ( dirty ); 0107 mPool.append ( newContactItem ); 0108 0109 return newContact; 0110 0111 } 0112 0113 JabberBaseContact *JabberContactPool::addGroupContact ( const XMPP::RosterItem &contact, bool roomContact, Kopete::MetaContact *metaContact, bool dirty ) 0114 { 0115 0116 XMPP::RosterItem mContact ( roomContact ? contact.jid().userHost () : contact.jid().full() ); 0117 0118 // see if the contact already exists 0119 JabberContactPoolItem *mContactItem = findPoolItem ( mContact ); 0120 if ( mContactItem) 0121 { 0122 if(mContactItem->contact()->inherits(roomContact ? 0123 (const char*)("JabberGroupContact") : (const char*)("JabberGroupMemberContact") ) ) 0124 { 0125 0126 qCDebug(JABBER_PROTOCOL_LOG) << "Updating existing contact " << mContact.jid().full(); 0127 0128 // It exists, update it. 0129 mContactItem->contact()->updateContact ( mContact ); 0130 mContactItem->setDirty ( dirty ); 0131 0132 //we must tell to the originating function that no new contact has been added 0133 return 0L;//mContactItem->contact (); 0134 } 0135 else 0136 { 0137 //this happen if we receive a MUC invitaiton: when the invitaiton is received, it's from the muc itself 0138 //and then kopete will create a temporary contact for it. but it will not be a good contact. 0139 qCDebug(JABBER_PROTOCOL_LOG) << "Bad contact will be removed and re-added " << mContact.jid().full(); 0140 Kopete::MetaContact *old_mc=mContactItem->contact()->metaContact(); 0141 delete mContactItem->contact(); 0142 mContactItem = 0L; 0143 if(old_mc->contacts().isEmpty() && old_mc!=metaContact) 0144 { 0145 Kopete::ContactList::self()->removeMetaContact( old_mc ); 0146 } 0147 0148 } 0149 0150 } 0151 0152 qCDebug(JABBER_PROTOCOL_LOG) << "Adding new contact " << mContact.jid().full(); 0153 0154 // create new contact instance and add it to the dictionary 0155 JabberBaseContact *newContact; 0156 0157 if ( roomContact ) 0158 newContact = new JabberGroupContact ( contact, mAccount, metaContact ); 0159 else 0160 newContact = new JabberGroupMemberContact ( contact, mAccount, metaContact ); 0161 0162 JabberContactPoolItem *newContactItem = new JabberContactPoolItem ( newContact ); 0163 0164 connect ( newContact, SIGNAL (contactDestroyed(Kopete::Contact*)), this, SLOT (slotContactDestroyed(Kopete::Contact*)) ); 0165 0166 newContactItem->setDirty ( dirty ); 0167 mPool.append ( newContactItem ); 0168 0169 return newContact; 0170 0171 } 0172 0173 void JabberContactPool::removeContact ( const XMPP::Jid &jid ) 0174 { 0175 qCDebug(JABBER_PROTOCOL_LOG) << "Removing contact " << jid.full(); 0176 0177 foreach(JabberContactPoolItem *mContactItem, mPool) 0178 { 0179 if ( mContactItem->contact()->rosterItem().jid().full().toLower() == jid.full().toLower() ) 0180 { 0181 /* 0182 * The following deletion will cause slotContactDestroyed() 0183 * to be called, which will clean the up the list. 0184 */ 0185 if(mContactItem->contact()) 0186 { 0187 Kopete::MetaContact *mc=mContactItem->contact()->metaContact(); 0188 delete mContactItem->contact (); 0189 if(mc && mc->contacts().isEmpty()) 0190 { 0191 Kopete::ContactList::self()->removeMetaContact(mc) ; 0192 } 0193 } 0194 return; 0195 } 0196 } 0197 0198 qCDebug(JABBER_PROTOCOL_LOG) << "WARNING: No match found!"; 0199 0200 } 0201 0202 void JabberContactPool::slotContactDestroyed ( Kopete::Contact *contact ) 0203 { 0204 qCDebug(JABBER_PROTOCOL_LOG) << "Contact deleted, collecting the pieces..."; 0205 0206 JabberBaseContact *jabberContact = static_cast<JabberBaseContact *>( contact ); 0207 //WARNING this ptr is not usable, we are in the Kopete::Contact destructor 0208 0209 // remove contact from the pool 0210 foreach(JabberContactPoolItem *mContactItem, mPool) 0211 { 0212 if ( mContactItem->contact() == jabberContact ) 0213 { 0214 JabberContactPoolItem *deletedItem = mPool.takeAt( mPool.indexOf(mContactItem) ); 0215 delete deletedItem; 0216 0217 break; 0218 } 0219 } 0220 0221 // delete all resources for it 0222 if(contact->account()==(Kopete::Account*)(mAccount)) 0223 mAccount->resourcePool()->removeAllResources ( XMPP::Jid ( contact->contactId() ) ); 0224 else 0225 { 0226 //this is a legacy contact. we have no way to get the real Jid at this point, we can only guess it. 0227 QString contactId= contact->contactId().replace('@','%') + '@' + contact->account()->myself()->contactId(); 0228 mAccount->resourcePool()->removeAllResources ( XMPP::Jid ( contactId ) ) ; 0229 } 0230 0231 } 0232 0233 void JabberContactPool::clear () 0234 { 0235 qCDebug(JABBER_PROTOCOL_LOG) << "Clearing the contact pool."; 0236 0237 foreach(JabberContactPoolItem *mContactItem, mPool) 0238 { 0239 /* 0240 * The following deletion will cause slotContactDestroyed() 0241 * to be called, which will clean the up the list. 0242 * NOTE: this is a very inefficient way to clear the list 0243 */ 0244 delete mContactItem->contact (); 0245 } 0246 0247 } 0248 0249 void JabberContactPool::setDirty ( const XMPP::Jid &jid, bool dirty ) 0250 { 0251 qCDebug(JABBER_PROTOCOL_LOG) << "Setting flag for " << jid.full() << " to " << dirty; 0252 0253 foreach(JabberContactPoolItem *mContactItem, mPool) 0254 { 0255 if ( mContactItem->contact()->rosterItem().jid().full().toLower() == jid.full().toLower() ) 0256 { 0257 mContactItem->setDirty ( dirty ); 0258 return; 0259 } 0260 } 0261 0262 qCDebug(JABBER_PROTOCOL_LOG) << "WARNING: No match found!"; 0263 0264 } 0265 0266 void JabberContactPool::cleanUp () 0267 { 0268 qCDebug(JABBER_PROTOCOL_LOG) << "Cleaning dirty items from contact pool."; 0269 0270 foreach(JabberContactPoolItem *mContactItem, mPool) 0271 { 0272 if ( mContactItem->dirty () ) 0273 { 0274 qCDebug(JABBER_PROTOCOL_LOG) << "Removing dirty contact " << mContactItem->contact()->contactId (); 0275 0276 /* 0277 * The following deletion will cause slotContactDestroyed() 0278 * to be called, which will clean the up the list. 0279 */ 0280 delete mContactItem->contact (); 0281 } 0282 } 0283 0284 } 0285 0286 JabberBaseContact *JabberContactPool::findExactMatch ( const XMPP::Jid &jid ) 0287 { 0288 0289 foreach(JabberContactPoolItem *mContactItem, mPool) 0290 { 0291 if ( mContactItem->contact()->rosterItem().jid().full().toLower () == jid.full().toLower () ) 0292 { 0293 return mContactItem->contact (); 0294 } 0295 } 0296 0297 return 0L; 0298 0299 } 0300 0301 JabberBaseContact *JabberContactPool::findRelevantRecipient ( const XMPP::Jid &jid ) 0302 { 0303 0304 foreach(JabberContactPoolItem *mContactItem, mPool) 0305 { 0306 if ( mContactItem->contact()->rosterItem().jid().full().toLower () == jid.userHost().toLower () ) 0307 { 0308 return mContactItem->contact (); 0309 } 0310 } 0311 0312 return 0L; 0313 0314 } 0315 0316 QList<JabberBaseContact*> JabberContactPool::findRelevantSources ( const XMPP::Jid &jid ) 0317 { 0318 QList<JabberBaseContact*> list; 0319 0320 foreach(JabberContactPoolItem *mContactItem, mPool) 0321 { 0322 if ( mContactItem->contact()->rosterItem().jid().userHost().toLower () == jid.userHost().toLower () ) 0323 { 0324 list.append ( mContactItem->contact () ); 0325 } 0326 } 0327 0328 return list; 0329 0330 } 0331 0332 JabberContactPoolItem::JabberContactPoolItem ( JabberBaseContact *contact ) 0333 { 0334 mDirty = true; 0335 mContact = contact; 0336 } 0337 0338 JabberContactPoolItem::~JabberContactPoolItem () 0339 { 0340 } 0341 0342 void JabberContactPoolItem::setDirty ( bool dirty ) 0343 { 0344 mDirty = dirty; 0345 } 0346 0347 bool JabberContactPoolItem::dirty () 0348 { 0349 return mDirty; 0350 } 0351 0352 JabberBaseContact *JabberContactPoolItem::contact () 0353 { 0354 return mContact; 0355 } 0356 0357 #include "moc_jabbercontactpool.cpp"