TDE network applications
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

356 lines
11KB

  1. /*
  2. * jabbercontactpool.cpp
  3. *
  4. * Copyright (c) 2004 by Till Gerken <till@tantalo.net>
  5. * Copyright (c) 2006 by Olivier Goffart <ogoffart at kde.org>
  6. *
  7. * Kopete (c) by the Kopete developers <kopete-devel@kde.org>
  8. *
  9. * *************************************************************************
  10. * * *
  11. * * This program is free software; you can redistribute it and/or modify *
  12. * * it under the terms of the GNU General Public License as published by *
  13. * * the Free Software Foundation; either version 2 of the License, or *
  14. * * (at your option) any later version. *
  15. * * *
  16. * *************************************************************************
  17. */
  18. #include "jabbercontactpool.h"
  19. #include <tqptrlist.h>
  20. #include <kdebug.h>
  21. #include <tdemessagebox.h>
  22. #include <kopeteaccountmanager.h>
  23. #include <kopetecontactlist.h>
  24. #include "kopeteuiglobal.h"
  25. #include "jabberprotocol.h"
  26. #include "jabberbasecontact.h"
  27. #include "jabbercontact.h"
  28. #include "jabbergroupcontact.h"
  29. #include "jabbergroupmembercontact.h"
  30. #include "jabberresourcepool.h"
  31. #include "jabberaccount.h"
  32. #include "jabbertransport.h"
  33. JabberContactPool::JabberContactPool ( JabberAccount *account )
  34. {
  35. // automatically delete all contacts in the pool upon removal
  36. mPool.setAutoDelete (true);
  37. mAccount = account;
  38. }
  39. JabberContactPool::~JabberContactPool ()
  40. {
  41. }
  42. JabberContactPoolItem *JabberContactPool::findPoolItem ( const XMPP::RosterItem &contact )
  43. {
  44. // see if the contact already exists
  45. for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ())
  46. {
  47. if ( mContactItem->contact()->rosterItem().jid().full().lower() == contact.jid().full().lower() )
  48. {
  49. return mContactItem;
  50. }
  51. }
  52. return 0;
  53. }
  54. JabberContact *JabberContactPool::addContact ( const XMPP::RosterItem &contact, Kopete::MetaContact *metaContact, bool dirty )
  55. {
  56. // see if the contact already exists
  57. JabberContactPoolItem *mContactItem = findPoolItem ( contact );
  58. if ( mContactItem)
  59. {
  60. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Updating existing contact " << contact.jid().full() << " - " << mContactItem->contact() << endl;
  61. // It exists, update it.
  62. mContactItem->contact()->updateContact ( contact );
  63. mContactItem->setDirty ( dirty );
  64. JabberContact *retval = dynamic_cast<JabberContact *>(mContactItem->contact ());
  65. if ( !retval )
  66. {
  67. KMessageBox::error ( Kopete::UI::Global::mainWidget (),
  68. "Fatal error in the Jabber contact pool. Please restart Kopete and submit a debug log "
  69. "of your session to http://bugs.trinitydesktop.org.",
  70. "Fatal Jabber Error" );
  71. }
  72. return retval;
  73. }
  74. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Adding new contact " << contact.jid().full() << endl;
  75. JabberTransport *transport=0l;
  76. TQString legacyId;
  77. //find if the contact should be added to a transport.
  78. if(mAccount->transports().contains(contact.jid().domain()))
  79. {
  80. transport=mAccount->transports()[contact.jid().domain()];
  81. legacyId=transport->legacyId( contact.jid() );
  82. }
  83. // create new contact instance and add it to the dictionary
  84. JabberContact *newContact = new JabberContact ( contact, transport ? (Kopete::Account*)transport : (Kopete::Account*)mAccount, metaContact , legacyId );
  85. JabberContactPoolItem *newContactItem = new JabberContactPoolItem ( newContact );
  86. connect ( newContact, TQT_SIGNAL ( contactDestroyed ( Kopete::Contact * ) ), this, TQT_SLOT ( slotContactDestroyed ( Kopete::Contact * ) ) );
  87. newContactItem->setDirty ( dirty );
  88. mPool.append ( newContactItem );
  89. return newContact;
  90. }
  91. JabberBaseContact *JabberContactPool::addGroupContact ( const XMPP::RosterItem &contact, bool roomContact, Kopete::MetaContact *metaContact, bool dirty )
  92. {
  93. XMPP::RosterItem mContact ( roomContact ? contact.jid().userHost () : contact.jid().full() );
  94. // see if the contact already exists
  95. JabberContactPoolItem *mContactItem = findPoolItem ( mContact );
  96. if ( mContactItem)
  97. {
  98. if(mContactItem->contact()->inherits(roomContact ?
  99. (const char*)("JabberGroupContact") : (const char*)("JabberGroupMemberContact") ) )
  100. {
  101. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Updating existing contact " << mContact.jid().full() << endl;
  102. // It exists, update it.
  103. mContactItem->contact()->updateContact ( mContact );
  104. mContactItem->setDirty ( dirty );
  105. //we must tell to the originating function that no new contact has been added
  106. return 0L;//mContactItem->contact ();
  107. }
  108. else
  109. {
  110. //this happen if we receive a MUC invitaiton: when the invitaiton is received, it's from the muc itself
  111. //and then kopete will create a temporary contact for it. but it will not be a good contact.
  112. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Bad contact will be removed and re-added " << mContact.jid().full() << endl;
  113. Kopete::MetaContact *old_mc=mContactItem->contact()->metaContact();
  114. delete mContactItem->contact();
  115. mContactItem = 0L;
  116. if(old_mc->contacts().isEmpty() && old_mc!=metaContact)
  117. {
  118. Kopete::ContactList::self()->removeMetaContact( old_mc );
  119. }
  120. }
  121. }
  122. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Adding new contact " << mContact.jid().full() << endl;
  123. // create new contact instance and add it to the dictionary
  124. JabberBaseContact *newContact;
  125. if ( roomContact )
  126. newContact = new JabberGroupContact ( contact, mAccount, metaContact );
  127. else
  128. newContact = new JabberGroupMemberContact ( contact, mAccount, metaContact );
  129. JabberContactPoolItem *newContactItem = new JabberContactPoolItem ( newContact );
  130. connect ( newContact, TQT_SIGNAL ( contactDestroyed ( Kopete::Contact * ) ), this, TQT_SLOT ( slotContactDestroyed ( Kopete::Contact * ) ) );
  131. newContactItem->setDirty ( dirty );
  132. mPool.append ( newContactItem );
  133. return newContact;
  134. }
  135. void JabberContactPool::removeContact ( const XMPP::Jid &jid )
  136. {
  137. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing contact " << jid.full() << endl;
  138. for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ())
  139. {
  140. if ( mContactItem->contact()->rosterItem().jid().full().lower() == jid.full().lower() )
  141. {
  142. /*
  143. * The following deletion will cause slotContactDestroyed()
  144. * to be called, which will clean the up the list.
  145. */
  146. if(mContactItem->contact())
  147. {
  148. Kopete::MetaContact *mc=mContactItem->contact()->metaContact();
  149. delete mContactItem->contact ();
  150. if(mc && mc->contacts().isEmpty())
  151. {
  152. Kopete::ContactList::self()->removeMetaContact(mc) ;
  153. }
  154. }
  155. return;
  156. }
  157. }
  158. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "WARNING: No match found!" << endl;
  159. }
  160. void JabberContactPool::slotContactDestroyed ( Kopete::Contact *contact )
  161. {
  162. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Contact deleted, collecting the pieces..." << endl;
  163. JabberBaseContact *jabberContact = static_cast<JabberBaseContact *>( contact );
  164. //WARNING this ptr is not usable, we are in the Kopete::Contact destructor
  165. // remove contact from the pool
  166. for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ())
  167. {
  168. if ( mContactItem->contact() == jabberContact )
  169. {
  170. mPool.remove ();
  171. break;
  172. }
  173. }
  174. // delete all resources for it
  175. if(contact->account()==(Kopete::Account*)(mAccount))
  176. mAccount->resourcePool()->removeAllResources ( XMPP::Jid ( contact->contactId() ) );
  177. else
  178. {
  179. //this is a legacy contact. we have no way to get the real Jid at this point, we can only guess it.
  180. TQString contactId= contact->contactId().replace('@','%') + "@" + contact->account()->myself()->contactId();
  181. mAccount->resourcePool()->removeAllResources ( XMPP::Jid ( contactId ) ) ;
  182. }
  183. }
  184. void JabberContactPool::clear ()
  185. {
  186. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Clearing the contact pool." << endl;
  187. for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ())
  188. {
  189. /*
  190. * The following deletion will cause slotContactDestroyed()
  191. * to be called, which will clean the up the list.
  192. * NOTE: this is a very inefficient way to clear the list
  193. */
  194. delete mContactItem->contact ();
  195. }
  196. }
  197. void JabberContactPool::setDirty ( const XMPP::Jid &jid, bool dirty )
  198. {
  199. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Setting flag for " << jid.full() << " to " << dirty << endl;
  200. for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ())
  201. {
  202. if ( mContactItem->contact()->rosterItem().jid().full().lower() == jid.full().lower() )
  203. {
  204. mContactItem->setDirty ( dirty );
  205. return;
  206. }
  207. }
  208. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "WARNING: No match found!" << endl;
  209. }
  210. void JabberContactPool::cleanUp ()
  211. {
  212. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Cleaning dirty items from contact pool." << endl;
  213. for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ())
  214. {
  215. if ( mContactItem->dirty () )
  216. {
  217. kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing dirty contact " << mContactItem->contact()->contactId () << endl;
  218. /*
  219. * The following deletion will cause slotContactDestroyed()
  220. * to be called, which will clean the up the list.
  221. */
  222. delete mContactItem->contact ();
  223. }
  224. }
  225. }
  226. JabberBaseContact *JabberContactPool::findExactMatch ( const XMPP::Jid &jid )
  227. {
  228. for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ())
  229. {
  230. if ( mContactItem->contact()->rosterItem().jid().full().lower () == jid.full().lower () )
  231. {
  232. return mContactItem->contact ();
  233. }
  234. }
  235. return 0L;
  236. }
  237. JabberBaseContact *JabberContactPool::findRelevantRecipient ( const XMPP::Jid &jid )
  238. {
  239. for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ())
  240. {
  241. if ( mContactItem->contact()->rosterItem().jid().full().lower () == jid.userHost().lower () )
  242. {
  243. return mContactItem->contact ();
  244. }
  245. }
  246. return 0L;
  247. }
  248. TQPtrList<JabberBaseContact> JabberContactPool::findRelevantSources ( const XMPP::Jid &jid )
  249. {
  250. TQPtrList<JabberBaseContact> list;
  251. for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ())
  252. {
  253. if ( mContactItem->contact()->rosterItem().jid().userHost().lower () == jid.userHost().lower () )
  254. {
  255. list.append ( mContactItem->contact () );
  256. }
  257. }
  258. return list;
  259. }
  260. JabberContactPoolItem::JabberContactPoolItem ( JabberBaseContact *contact )
  261. {
  262. mDirty = true;
  263. mContact = contact;
  264. }
  265. JabberContactPoolItem::~JabberContactPoolItem ()
  266. {
  267. }
  268. void JabberContactPoolItem::setDirty ( bool dirty )
  269. {
  270. mDirty = dirty;
  271. }
  272. bool JabberContactPoolItem::dirty ()
  273. {
  274. return mDirty;
  275. }
  276. JabberBaseContact *JabberContactPoolItem::contact ()
  277. {
  278. return mContact;
  279. }
  280. #include "jabbercontactpool.moc"