File indexing completed on 2024-04-14 04:01:44

0001  /*
0002   * jabbercontact.cpp  -  Base class for the Kopete Jabber protocol contact
0003   *
0004   * Copyright (c) 2002-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 <KLocalizedString>
0021 #include <KStandardDirs>
0022 #include <QTimer>
0023 #include <QImage>
0024 #include <QRegExp>
0025 #include <KMessageBox>
0026 #include <kio/netaccess.h>
0027 
0028 
0029 #include <kopetegroup.h>
0030 #include <kopetecontactlist.h>
0031 #include <kopeteavatarmanager.h>
0032 
0033 #include "jabberbasecontact.h"
0034 
0035 #include "xmpp_tasks.h"
0036 
0037 #include "jabberprotocol.h"
0038 #include "jabberaccount.h"
0039 #include "jabberresource.h"
0040 #include "jabberresourcepool.h"
0041 #include "kopetemetacontact.h"
0042 #include "kopetemessage.h"
0043 #include "kopeteuiglobal.h"
0044 #include "jabbertransport.h"
0045 #include "dlgjabbervcard.h"
0046 
0047 
0048 /**
0049  * JabberBaseContact constructor
0050  */
0051 JabberBaseContact::JabberBaseContact (const XMPP::RosterItem &rosterItem, Kopete::Account *account, Kopete::MetaContact * mc, const QString &legacyId)
0052     : Kopete::Contact (account, legacyId.isEmpty() ? rosterItem.jid().full() : legacyId , mc )
0053 {
0054     setDontSync ( false );
0055     
0056     JabberTransport *t=transport();
0057     m_account= t ? t->account() : static_cast<JabberAccount *>(Kopete::Contact::account());
0058 
0059 
0060     // take roster item and update display name
0061     updateContact ( rosterItem );
0062 
0063 }
0064 
0065 
0066 JabberProtocol *JabberBaseContact::protocol ()
0067 {
0068 
0069     return static_cast<JabberProtocol *>(Kopete::Contact::protocol ());
0070 }
0071 
0072 
0073 JabberTransport * JabberBaseContact::transport( )
0074 {
0075     return dynamic_cast<JabberTransport*>(Kopete::Contact::account());
0076 }
0077 
0078 
0079 /* Return if we are reachable (defaults to true because
0080    we can send on- and offline, only return false if the
0081    account itself is offline, too) */
0082 bool JabberBaseContact::isReachable ()
0083 {
0084     if (account()->isConnected())
0085         return true;
0086 
0087     return false;
0088 
0089 }
0090 
0091 void JabberBaseContact::updateContact ( const XMPP::RosterItem & item )
0092 {
0093     qCDebug(JABBER_PROTOCOL_LOG) << "Synchronizing local copy of " << contactId() << " with information received from server.  (name='" << item.name() << "' groups='" << item.groups() << "')";
0094 
0095     mRosterItem = item;
0096 
0097     // if we don't have a meta contact yet, stop processing here
0098     if ( !metaContact () )
0099         return;
0100 
0101     /*
0102      * We received the information from the server, as such,
0103      * don't attempt to synch while we update our local copy.
0104      */
0105     setDontSync ( true );
0106 
0107     // The myself contact is not in the roster on server, ignore this code
0108     // because the myself MetaContact displayname become the latest 
0109     // Jabber acccount jid.
0110     if( metaContact() != Kopete::ContactList::self()->myself() )
0111     {
0112         // only update the alias if it is not empty
0113         if ( !item.name().isEmpty () && item.name() != item.jid().bare() 
0114             && metaContact()->customDisplayName() != item.name () )
0115         {
0116             qCDebug(JABBER_PROTOCOL_LOG) << "setting display name of " << contactId () << " to " << item.name();
0117             metaContact()->setDisplayName ( item.name () );
0118         }
0119     }
0120 
0121     /*
0122      * Set the contact's subscription status
0123      */
0124     switch ( item.subscription().type () )
0125     {
0126         case XMPP::Subscription::None:
0127             setProperty ( protocol()->propSubscriptionStatus,
0128                           i18n ( "You cannot see each others' status." ) );
0129             break;
0130         case XMPP::Subscription::To:
0131             setProperty ( protocol()->propSubscriptionStatus,
0132                           i18n ( "You can see this contact's status, but he/she cannot see your status." ) );
0133             break;
0134         case XMPP::Subscription::From:
0135             setProperty ( protocol()->propSubscriptionStatus,
0136                           i18n ( "This contact can see your status, but you cannot see his/her status." ) );
0137             break;
0138         case XMPP::Subscription::Both:
0139             setProperty ( protocol()->propSubscriptionStatus,
0140                           i18n ( "You can see each others' status." ) );
0141             break;
0142     }
0143 
0144     if( !metaContact()->isTemporary() )
0145     {
0146         /*
0147         * In this method, as opposed to KC::syncGroups(),
0148         * the group list from the server is authoritative.
0149         * As such, we need to find a list of all groups
0150         * that the meta contact resides in but does not
0151         * reside in on the server anymore, as well as all
0152         * groups that the meta contact does not reside in,
0153         * but resides in on the server.
0154         * Then, we'll have to synchronize the KMC using
0155         * that information.
0156         */
0157         Kopete::GroupList groupsToRemoveFrom, groupsToAddTo;
0158     
0159         // find all groups our contact is in but that are not in the server side roster
0160         for ( int i = 0; i < metaContact()->groups().count (); i++ )
0161         {
0162             if ( !item.groups().contains ( metaContact()->groups().at(i)->displayName () ) )
0163                 groupsToRemoveFrom.append ( metaContact()->groups().at ( i ) );
0164         }
0165     
0166         // now find all groups that are in the server side roster but not in the local group
0167         for ( int i = 0; i < item.groups().count (); i++ )
0168         {
0169             bool found = false;
0170             for ( int j = 0; j < metaContact()->groups().count (); j++)
0171             {
0172                 if ( metaContact()->groups().at(j)->displayName () == item.groups().at(i) )
0173                 {
0174                     found = true;
0175                     break;
0176                 }
0177             }
0178             
0179             if ( !found )
0180             {
0181                 groupsToAddTo.append ( Kopete::ContactList::self()->findGroup ( item.groups().at(i) ) );
0182             }
0183         }
0184     
0185         /*
0186         * Special case: if we don't add the contact to any group and the
0187         * list of groups to remove from contains the top level group, we
0188         * risk removing the contact from the visible contact list. In this
0189         * case, we need to make sure at least the top level group stays.
0190         */
0191         if ( ( groupsToAddTo.count () == 0 ) && ( groupsToRemoveFrom.contains ( Kopete::Group::topLevel () ) ) )
0192         {
0193             groupsToRemoveFrom.removeAll ( Kopete::Group::topLevel () );
0194         }
0195     
0196         foreach ( Kopete::Group *group, groupsToRemoveFrom )
0197         {
0198             qCDebug(JABBER_PROTOCOL_LOG) << "Removing " << contactId() << " from group " << group->displayName ();
0199             metaContact()->removeFromGroup ( group );
0200         }
0201     
0202         foreach ( Kopete::Group *group, groupsToAddTo )
0203         {
0204             qCDebug(JABBER_PROTOCOL_LOG) << "Adding " << contactId() << " to group " << group->displayName ();
0205             metaContact()->addToGroup ( group );
0206         }
0207     }
0208 
0209     /*
0210      * Enable updates for the server again.
0211      */
0212     setDontSync ( false );
0213     
0214     //can't do it now because it's called from contructor at a point some virtual function are not available
0215     QTimer::singleShot(0, this, SLOT(reevaluateStatus()));
0216 
0217 }
0218 
0219 void JabberBaseContact::updateResourceList ()
0220 {
0221     /*
0222      * Set available resources.
0223      * This is a bit more complicated: We need to generate
0224      * all images dynamically from the KOS icons and store
0225      * them into the mime factory, then plug them into
0226      * the richtext.
0227      */
0228     JabberResourcePool::ResourceList resourceList;
0229     account()->resourcePool()->findResources ( rosterItem().jid() , resourceList );
0230 
0231     if ( resourceList.isEmpty () )
0232     {
0233         removeProperty ( protocol()->propAvailableResources );
0234         return;
0235     }
0236 
0237     QString resourceListStr = "<table cellspacing=\"0\">";
0238 
0239     for ( JabberResourcePool::ResourceList::iterator it = resourceList.begin (); it != resourceList.end (); ++it )
0240     {
0241         // icon, resource name and priority
0242         resourceListStr += QString ( "<tr><td><img src=\"kopete-onlinestatus-icon:%1\" /> <b>%2</b> (Priority: %3)</td></tr>" ).
0243                            arg ( protocol()->resourceToKOS((*it)->resource()).mimeSourceFor ( account () ),
0244                                  (*it)->resource().name (), QString::number ( (*it)->resource().priority () ) );
0245 
0246         // client name, version, OS
0247         if ( !(*it)->clientName().isEmpty () )
0248         {
0249             resourceListStr += QString ( "<tr><td>%1: %2 (%3)</td></tr>" ).
0250                                arg ( i18n ( "Client" ), (*it)->clientName (), (*it)->clientSystem () );
0251         }
0252         
0253         // Supported features
0254 #if 0  //disabled because it's just an ugly and long list of incomprehensible namespaces to the user
0255         QStringList supportedFeatures = (*it)->features().list();
0256         QStringList::ConstIterator featuresIt, featuresItEnd = supportedFeatures.constEnd();
0257         if( !supportedFeatures.empty() )
0258             resourceListStr += QString( "<tr><td>Supported Features:" );
0259         for( featuresIt = supportedFeatures.constBegin(); featuresIt != featuresItEnd; ++featuresIt )
0260         {
0261             XMPP::Features tempFeature(*featuresIt);
0262             resourceListStr += QString("\n<br>");
0263             if ( tempFeature.id() > XMPP::Features::FID_None )
0264                 resourceListStr += tempFeature.name() + QString(" (");
0265             resourceListStr += *featuresIt;
0266             if ( tempFeature.id() > Features::FID_None )
0267                 resourceListStr += QString(")");    
0268         }
0269         if( !supportedFeatures.empty() )
0270             resourceListStr += QString( "</td></tr>" );
0271 #endif
0272         
0273         // resource timestamp
0274         resourceListStr += QString ( "<tr><td>%1: %2</td></tr>" ).
0275                            arg ( i18n ( "Timestamp" ), KLocale::global()->formatDateTime ( (*it)->resource().status().timeStamp(), KLocale::ShortDate, true ) );
0276 
0277         // message, if any
0278         if ( !(*it)->resource().status().status().trimmed().isEmpty () )
0279         {
0280             resourceListStr += QString ( "<tr><td>%1: %2</td></tr>" ).
0281                                arg ( 
0282                                 i18n ( "Message" ), 
0283                                 Kopete::Message::escape( (*it)->resource().status().status () ) 
0284                                 );
0285         }
0286     }
0287     
0288     resourceListStr += "</table>";
0289     
0290     setProperty ( protocol()->propAvailableResources, resourceListStr );
0291 }
0292 
0293 void JabberBaseContact::reevaluateStatus ()
0294 {
0295     qCDebug(JABBER_PROTOCOL_LOG) << "Determining new status for " << contactId ();
0296 
0297     Kopete::OnlineStatus status;
0298     XMPP::Resource resource = account()->resourcePool()->bestResource ( mRosterItem.jid () );
0299 
0300     status = protocol()->resourceToKOS ( resource );
0301     
0302     
0303     /* Add some icon to show the subscription */ 
0304     if( ( mRosterItem.subscription().type() == XMPP::Subscription::None || mRosterItem.subscription().type() == XMPP::Subscription::From)
0305              && inherits ( "JabberContact" ) && metaContact() != Kopete::ContactList::self()->myself() && account()->isConnected() )
0306     {
0307         status = Kopete::OnlineStatus(status.status() ,
0308                                       status.weight() ,
0309                                       protocol() ,
0310                                       status.internalStatus() | 0x0100,
0311                                       status.overlayIcons() + QStringList("status_unknown_overlay") , //FIXME: find better icon
0312                                       status.description() );
0313     }
0314     
0315 
0316     updateResourceList ();
0317 
0318     qCDebug(JABBER_PROTOCOL_LOG) << "New status for " << contactId () << " is " << status.description ();
0319     setOnlineStatus ( status );
0320 
0321     /*
0322      * Set away message property.
0323      * We just need to read it from the current resource.
0324      */
0325     setStatusMessage( resource.status().status() );
0326 
0327 }
0328 
0329 QString JabberBaseContact::fullAddress ()
0330 {
0331 
0332     XMPP::Jid jid = rosterItem().jid();
0333 
0334     if ( jid.resource().isEmpty () )
0335     {
0336         jid.setResource ( account()->resourcePool()->bestResource ( jid ).name () );
0337     }
0338 
0339     return jid.full ();
0340 
0341 }
0342 
0343 XMPP::Jid JabberBaseContact::bestAddress ()
0344 {
0345 
0346     // see if we are subscribed with a preselected resource
0347     if ( !mRosterItem.jid().resource().isEmpty () )
0348     {
0349         // we have a preselected resource, so return our default full address
0350         return mRosterItem.jid ();
0351     }
0352 
0353     // construct address out of user@host and current best resource
0354     XMPP::Jid jid = mRosterItem.jid ();
0355     jid.setResource ( account()->resourcePool()->bestResource( mRosterItem.jid() ).name () );
0356 
0357     return jid;
0358 
0359 }
0360 
0361 void JabberBaseContact::setDontSync ( bool flag )
0362 {
0363 
0364     mDontSync = flag;
0365 
0366 }
0367 
0368 bool JabberBaseContact::dontSync ()
0369 {
0370 
0371     return mDontSync;
0372 
0373 }
0374 
0375 void JabberBaseContact::serialize (QMap < QString, QString > &serializedData, QMap < QString, QString > & /* addressBookData */ )
0376 {
0377 
0378     // Contact id and display name are already set for us, only add the rest
0379     serializedData["JID"] = mRosterItem.jid().full();
0380 
0381     serializedData["groups"] = mRosterItem.groups ().join ( QLatin1String( QString::fromLatin1 ("," )));
0382 }
0383 
0384 void JabberBaseContact::slotUserInfo( )
0385 {
0386     if ( !account()->isConnected () )
0387     {
0388         account()->errorConnectFirst ();
0389         return;
0390     }
0391     
0392     // Update the vCard
0393     //slotGetTimedVCard();
0394 
0395     new dlgJabberVCard ( account(), this, Kopete::UI::Global::mainWidget () );
0396 }
0397 
0398 void JabberBaseContact::setPropertiesFromVCard ( const XMPP::VCard &vCard )
0399 {
0400     qCDebug(JABBER_PROTOCOL_LOG) << "Updating vCard for " << contactId ();
0401 
0402     // update vCard cache timestamp if this is not a temporary contact
0403     if ( metaContact() && !metaContact()->isTemporary () )
0404     {
0405         setProperty ( protocol()->propVCardCacheTimeStamp, QDateTime::currentDateTime().toString ( Qt::ISODate ) );
0406     }
0407 
0408     
0409     /*
0410     * Set the nickname property.
0411     *  but ignore it if we are in a groupchat, or it will clash with the normal nickname
0412     */
0413     if(inherits ( "JabberContact" ))
0414     {
0415         if ( !vCard.nickName().isEmpty () )
0416         {
0417             setProperty ( protocol()->propNickName, vCard.nickName () );
0418         }
0419         else if ( !vCard.fullName().isEmpty () ) // google talk contacts for example do not have a nickname; better show fullname instead of jabber id
0420         {
0421             setProperty ( protocol()->propNickName, vCard.fullName () );
0422         }
0423         else
0424         {
0425             removeProperty ( protocol()->propNickName );
0426         }
0427     }
0428 
0429     /**
0430      * Kopete does not allow a modification of the "full name"
0431      * property. However, some vCards specify only the full name,
0432      * some specify only first and last name.
0433      * Due to these inconsistencies, if first and last name don't
0434      * exist, it is attempted to parse the full name.
0435      */
0436 
0437     // remove all properties first
0438     removeProperty ( protocol()->propFirstName );
0439     removeProperty ( protocol()->propLastName );
0440     removeProperty ( protocol()->propFullName );
0441 
0442     if ( !vCard.fullName().isEmpty () && vCard.givenName().isEmpty () && vCard.familyName().isEmpty () )
0443     {
0444         QString lastName = vCard.fullName().section ( ' ', 0, -1 );
0445         QString firstName = vCard.fullName().left(vCard.fullName().length () - lastName.length ()).trimmed ();
0446 
0447         setProperty ( protocol()->propFirstName, firstName );
0448         setProperty ( protocol()->propLastName, lastName );
0449     }
0450     else
0451     {
0452         if ( !vCard.givenName().isEmpty () )
0453             setProperty ( protocol()->propFirstName, vCard.givenName () );
0454 
0455         if ( !vCard.familyName().isEmpty () )
0456             setProperty ( protocol()->propLastName, vCard.familyName () );
0457     }
0458     if( !vCard.fullName().isEmpty() )
0459         setProperty ( protocol()->propFullName, vCard.fullName() );
0460 
0461     /* 
0462     * Set the general information 
0463     */
0464     removeProperty( protocol()->propJid );
0465     removeProperty( protocol()->propBirthday );
0466     removeProperty( protocol()->propTimezone );
0467     removeProperty( protocol()->propHomepage );
0468 
0469     setProperty( protocol()->propJid, vCard.jid() );
0470     
0471     if( !vCard.bdayStr().isEmpty () )
0472         setProperty( protocol()->propBirthday, vCard.bdayStr() );
0473     if( !vCard.timezone().isEmpty () )
0474         setProperty( protocol()->propTimezone, vCard.timezone() );
0475     if( !vCard.url().isEmpty () )
0476         setProperty( protocol()->propHomepage, vCard.url() );
0477 
0478     /*
0479     * Set the work information.
0480     */
0481     removeProperty( protocol()->propCompanyName );
0482     removeProperty( protocol()->propCompanyDepartement );
0483     removeProperty( protocol()->propCompanyPosition );
0484     removeProperty( protocol()->propCompanyRole );
0485     
0486     if( !vCard.org().name.isEmpty() )
0487         setProperty( protocol()->propCompanyName, vCard.org().name );
0488     if( !vCard.org().unit.join( QLatin1String( "," )).isEmpty() )
0489         setProperty( protocol()->propCompanyDepartement, vCard.org().unit.join( QLatin1String( "," ))) ;
0490     if( !vCard.title().isEmpty() )
0491         setProperty( protocol()->propCompanyPosition, vCard.title() );
0492     if( !vCard.role().isEmpty() )
0493         setProperty( protocol()->propCompanyRole, vCard.role() );
0494 
0495     /*
0496     * Set the about information
0497     */
0498     removeProperty( protocol()->propAbout );
0499 
0500     if( !vCard.desc().isEmpty() )
0501         setProperty( protocol()->propAbout, vCard.desc() );
0502 
0503     
0504     /*
0505     * Set the work and home addresses information
0506     */
0507     removeProperty( protocol()->propWorkStreet );
0508     removeProperty( protocol()->propWorkExtAddr );
0509     removeProperty( protocol()->propWorkPOBox );
0510     removeProperty( protocol()->propWorkCity );
0511     removeProperty( protocol()->propWorkPostalCode );
0512     removeProperty( protocol()->propWorkCountry );
0513 
0514     removeProperty( protocol()->propHomeStreet );
0515     removeProperty( protocol()->propHomeExtAddr );
0516     removeProperty( protocol()->propHomePOBox );
0517     removeProperty( protocol()->propHomeCity );
0518     removeProperty( protocol()->propHomePostalCode );
0519     removeProperty( protocol()->propHomeCountry );
0520 
0521     for(XMPP::VCard::AddressList::const_iterator it = vCard.addressList().begin(); it != vCard.addressList().end(); it++)
0522     {
0523         XMPP::VCard::Address address = (*it);
0524 
0525         if(address.work)
0526         {
0527             setProperty( protocol()->propWorkStreet, address.street );
0528             setProperty( protocol()->propWorkExtAddr, address.extaddr );
0529             setProperty( protocol()->propWorkPOBox, address.pobox );
0530             setProperty( protocol()->propWorkCity, address.locality );
0531             setProperty( protocol()->propWorkPostalCode, address.pcode );
0532             setProperty( protocol()->propWorkCountry, address.country );
0533         }
0534         else
0535             if(address.home)
0536         {
0537             setProperty( protocol()->propHomeStreet, address.street );
0538             setProperty( protocol()->propHomeExtAddr, address.extaddr );
0539             setProperty( protocol()->propHomePOBox, address.pobox );
0540             setProperty( protocol()->propHomeCity, address.locality );
0541             setProperty( protocol()->propHomePostalCode, address.pcode );
0542             setProperty( protocol()->propHomeCountry, address.country );
0543         }
0544     }
0545 
0546 
0547     /*
0548     * Delete emails first, they might not be present
0549     * in the vCard at all anymore.
0550     */
0551     removeProperty ( protocol()->propEmailAddress );
0552     removeProperty ( protocol()->propWorkEmailAddress );
0553 
0554     /*
0555     * Set the home and work email information.
0556     */
0557     XMPP::VCard::EmailList::const_iterator emailEnd = vCard.emailList().end ();
0558     for(XMPP::VCard::EmailList::const_iterator it = vCard.emailList().begin(); it != emailEnd; ++it)
0559     {
0560         XMPP::VCard::Email email = (*it);
0561         
0562         if(email.work)
0563         {
0564             if( !email.userid.isEmpty() )
0565                 setProperty ( protocol()->propWorkEmailAddress, email.userid );
0566         }
0567         else
0568             if(email.home)
0569         {   
0570             if( !email.userid.isEmpty() )
0571                 setProperty ( protocol()->propEmailAddress, email.userid );
0572         }
0573     }
0574 
0575     /*
0576     * Delete phone number properties first as they might have
0577     * been unset during an update and are not present in
0578     * the vCard at all anymore.
0579     */
0580     removeProperty ( protocol()->propPrivatePhone );
0581     removeProperty ( protocol()->propPrivateMobilePhone );
0582     removeProperty ( protocol()->propWorkPhone );
0583     removeProperty ( protocol()->propWorkMobilePhone );
0584 
0585     /*
0586     * Set phone numbers. Note that if a mobile phone number
0587     * is specified, it's assigned to the private mobile
0588     * phone number property. This might not be the desired
0589     * behavior for all users.
0590     */
0591     XMPP::VCard::PhoneList::const_iterator phoneEnd = vCard.phoneList().end ();
0592     for(XMPP::VCard::PhoneList::const_iterator it = vCard.phoneList().begin(); it != phoneEnd; ++it)
0593     {
0594         XMPP::VCard::Phone phone = (*it);
0595 
0596         if(phone.work)
0597         {
0598             setProperty ( protocol()->propWorkPhone, phone.number );
0599         }
0600         else
0601             if(phone.fax)
0602         {
0603             setProperty ( protocol()->propPhoneFax, phone.number);
0604         }
0605         else
0606             if(phone.cell)
0607         {
0608             setProperty ( protocol()->propPrivateMobilePhone, phone.number );
0609         }
0610         else
0611             if(phone.home)
0612         {
0613             setProperty ( protocol()->propPrivatePhone, phone.number );
0614         }
0615 
0616     }
0617 
0618     /*
0619     * Set photo/avatar property.
0620     */
0621     removeProperty( protocol()->propPhoto );
0622 
0623     QImage contactPhoto;
0624     
0625     // photo() is a QByteArray
0626     if ( !vCard.photo().isEmpty() )
0627     {
0628         qCDebug(JABBER_PROTOCOL_LOG) << "Contact has a photo embedded into his vCard.";
0629 
0630         // QImage is used to save to disk in PNG later.
0631         contactPhoto = QImage::fromData( vCard.photo() );
0632     }
0633     // Contact photo is a URI.
0634     else if( !vCard.photoURI().isEmpty() )
0635     {
0636         QString tempPhotoPath = 0;
0637         
0638         // Downalod photo from URI.
0639         if( !KIO::NetAccess::download( vCard.photoURI(), tempPhotoPath, 0) ) 
0640         {
0641             KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget (), KMessageBox::Error, i18n( "Downloading of Jabber contact photo failed." ) );
0642             return;
0643         }
0644 
0645 
0646         qCDebug(JABBER_PROTOCOL_LOG) << "Contact photo is a URI.";
0647 
0648         contactPhoto = QImage( tempPhotoPath );
0649         
0650         KIO::NetAccess::removeTempFile(  tempPhotoPath );
0651     }
0652 
0653     // add the entry using the avatar manager
0654     Kopete::AvatarManager::AvatarEntry entry;
0655     entry.name = contactId();
0656     entry.image = contactPhoto;
0657     entry.category = Kopete::AvatarManager::Contact;
0658     entry.contact = this;   
0659     entry = Kopete::AvatarManager::self()->add(entry);
0660 
0661     // Save the image to the disk, then set the property.
0662     if(!entry.path.isNull())
0663     {
0664         qCDebug(JABBER_PROTOCOL_LOG) << "Setting photo for contact: " << contactId();
0665         setProperty( protocol()->propPhoto, entry.path );
0666     }
0667 
0668 }
0669 
0670 #include "moc_jabberbasecontact.cpp"
0671 
0672 // vim: set noet ts=4 sts=4 sw=4: