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.
1500 lines
49 KiB
1500 lines
49 KiB
5 years ago
|
/*
|
||
|
msnaccount.h - Manages a single MSN account
|
||
|
|
||
|
Copyright (c) 2003-2005 by Olivier Goffart <ogoffart@ kde.org>
|
||
|
Copyright (c) 2003 by Martijn Klingens <klingens@kde.org>
|
||
|
Copyright (c) 2005 by Michaël Larouche <michael.larouche@kdemail.net>
|
||
|
|
||
|
Kopete (c) 2002-2005 by the Kopete developers <kopete-devel@kde.org>
|
||
|
|
||
|
*************************************************************************
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||
|
* (at your option) any later version. *
|
||
|
* *
|
||
|
*************************************************************************
|
||
|
*/
|
||
|
|
||
|
#include "msnaccount.h"
|
||
|
|
||
|
#include <config.h>
|
||
|
|
||
|
#include <tdeaction.h>
|
||
|
#include <tdeconfig.h>
|
||
|
#include <kdebug.h>
|
||
|
#include <kinputdialog.h>
|
||
|
#include <tdemessagebox.h>
|
||
|
#include <tdepopupmenu.h>
|
||
|
#include <kstandarddirs.h>
|
||
|
#include <kmdcodec.h>
|
||
|
#include <tdelocale.h>
|
||
|
|
||
|
#include <tqfile.h>
|
||
|
#include <tqregexp.h>
|
||
|
#include <tqvalidator.h>
|
||
|
#include <tqimage.h>
|
||
|
|
||
|
#include "msncontact.h"
|
||
|
#include "msnnotifysocket.h"
|
||
|
#include "msnchatsession.h"
|
||
|
#include "kopetecontactlist.h"
|
||
|
#include "kopetegroup.h"
|
||
|
#include "kopetemetacontact.h"
|
||
|
#include "kopetepassword.h"
|
||
|
#include "kopeteuiglobal.h"
|
||
|
#include "kopeteglobal.h"
|
||
|
#include "kopetechatsessionmanager.h"
|
||
|
#include "contactaddednotifydialog.h"
|
||
|
#include "kopeteutils.h"
|
||
|
|
||
|
#include "sha1.h"
|
||
|
|
||
|
|
||
|
#if !defined NDEBUG
|
||
|
#include "msndebugrawcmddlg.h"
|
||
|
#include <tdeglobal.h>
|
||
|
#endif
|
||
|
|
||
|
#if MSN_WEBCAM
|
||
|
#include "avdevice/videodevicepool.h"
|
||
|
#endif
|
||
|
|
||
|
MSNAccount::MSNAccount( MSNProtocol *parent, const TQString& AccountID, const char *name )
|
||
|
: Kopete::PasswordedAccount ( parent, AccountID.lower(), 0, name )
|
||
|
{
|
||
|
m_notifySocket = 0L;
|
||
|
m_connectstatus = MSNProtocol::protocol()->NLN;
|
||
|
m_addWizard_metaContact = 0L;
|
||
|
m_newContactList=false;
|
||
|
|
||
|
// Init the myself contact
|
||
|
setMyself( new MSNContact( this, accountId(), Kopete::ContactList::self()->myself() ) );
|
||
|
//myself()->setOnlineStatus( MSNProtocol::protocol()->FLN );
|
||
|
|
||
|
TQObject::connect( Kopete::ContactList::self(), TQT_SIGNAL( groupRenamed( Kopete::Group *, const TQString & ) ),
|
||
|
TQT_SLOT( slotKopeteGroupRenamed( Kopete::Group * ) ) );
|
||
|
TQObject::connect( Kopete::ContactList::self(), TQT_SIGNAL( groupRemoved( Kopete::Group * ) ),
|
||
|
TQT_SLOT( slotKopeteGroupRemoved( Kopete::Group * ) ) );
|
||
|
|
||
|
TQObject::connect( Kopete::ContactList::self(), TQT_SIGNAL( globalIdentityChanged(const TQString&, const TQVariant& ) ), TQT_SLOT( slotGlobalIdentityChanged(const TQString&, const TQVariant& ) ));
|
||
|
|
||
|
m_openInboxAction = new TDEAction( i18n( "Open Inbo&x..." ), "mail_generic", 0, this, TQT_SLOT( slotOpenInbox() ), this, "m_openInboxAction" );
|
||
|
m_changeDNAction = new TDEAction( i18n( "&Change Display Name..." ), TQString(), 0, this, TQT_SLOT( slotChangePublicName() ), this, "renameAction" );
|
||
|
m_startChatAction = new TDEAction( i18n( "&Start Chat..." ), "mail_generic", 0, this, TQT_SLOT( slotStartChat() ), this, "startChatAction" );
|
||
|
|
||
|
|
||
|
TDEConfigGroup *config=configGroup();
|
||
|
|
||
|
m_blockList = config->readListEntry( "blockList" ) ;
|
||
|
m_allowList = config->readListEntry( "allowList" ) ;
|
||
|
m_reverseList = config->readListEntry( "reverseList" ) ;
|
||
|
|
||
|
// Load the avatar
|
||
|
m_pictureFilename = locateLocal( "appdata", "msnpicture-"+ accountId().lower().replace(TQRegExp("[./~]"),"-") +".png" );
|
||
|
resetPictureObject(true);
|
||
|
|
||
|
static_cast<MSNContact *>( myself() )->setInfo( "PHH", config->readEntry("PHH") );
|
||
|
static_cast<MSNContact *>( myself() )->setInfo( "PHM", config->readEntry("PHM") );
|
||
|
static_cast<MSNContact *>( myself() )->setInfo( "PHW", config->readEntry("PHW") );
|
||
|
//this is the display name
|
||
|
static_cast<MSNContact *>( myself() )->setInfo( "MFN", config->readEntry("MFN") );
|
||
|
|
||
|
//construct the group list
|
||
|
//Before 2003-11-14 the MSN server allowed us to download the group list without downloading the whole contactlist, but it's not possible anymore
|
||
|
TQPtrList<Kopete::Group> groupList = Kopete::ContactList::self()->groups();
|
||
|
for ( Kopete::Group *g = groupList.first(); g; g = groupList.next() )
|
||
|
{
|
||
|
TQString groupGuid=g->pluginData( protocol(), accountId() + " id" );
|
||
|
if ( !groupGuid.isEmpty() )
|
||
|
m_groupList.insert( groupGuid , g );
|
||
|
}
|
||
|
|
||
|
// Set the client Id for the myself contact. It sets what MSN feature we support.
|
||
|
m_clientId = MSNProtocol::MSNC4 | MSNProtocol::InkFormatGIF | MSNProtocol::SupportMultiPacketMessaging;
|
||
|
|
||
|
#if MSN_WEBCAM
|
||
|
Kopete::AV::VideoDevicePool::self()->scanDevices();
|
||
|
if( Kopete::AV::VideoDevicePool::self()->hasDevices() )
|
||
|
{
|
||
|
m_clientId |= MSNProtocol::SupportWebcam;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
TQString MSNAccount::serverName()
|
||
|
{
|
||
|
return configGroup()->readEntry( "serverName" , "messenger.hotmail.com" );
|
||
|
}
|
||
|
|
||
|
uint MSNAccount::serverPort()
|
||
|
{
|
||
|
return configGroup()->readNumEntry( "serverPort" , 1863 );
|
||
|
}
|
||
|
|
||
|
bool MSNAccount::useHttpMethod() const
|
||
|
{
|
||
|
return configGroup()->readBoolEntry( "useHttpMethod" , false );
|
||
|
}
|
||
|
|
||
|
TQString MSNAccount::myselfClientId() const
|
||
|
{
|
||
|
return TQString::number(m_clientId, 10);
|
||
|
}
|
||
|
|
||
|
void MSNAccount::connectWithPassword( const TQString &passwd )
|
||
|
{
|
||
|
m_newContactList=false;
|
||
|
if ( isConnected() )
|
||
|
{
|
||
|
kdDebug( 14140 ) << k_funcinfo <<"Ignoring Connect request "
|
||
|
<< "(Already Connected)" << endl;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( m_notifySocket )
|
||
|
{
|
||
|
kdDebug( 14140 ) << k_funcinfo <<"Ignoring Connect request (Already connecting)" << endl;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_password = passwd;
|
||
|
|
||
|
if ( m_password.isNull() )
|
||
|
{
|
||
|
kdDebug( 14140 ) << k_funcinfo <<"Abort connection (null password)" << endl;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( contacts().count() <= 1 )
|
||
|
{
|
||
|
// Maybe the contactlist.xml has been removed, and the serial number not updated
|
||
|
// ( the 1 is for the myself contact )
|
||
|
configGroup()->writeEntry( "serial", 0 );
|
||
|
}
|
||
|
|
||
|
m_openInboxAction->setEnabled( false );
|
||
|
|
||
|
createNotificationServer(serverName(), serverPort());
|
||
|
}
|
||
|
|
||
|
void MSNAccount::createNotificationServer( const TQString &host, uint port )
|
||
|
{
|
||
|
if(m_notifySocket) //we are switching from one to another notifysocket.
|
||
|
{
|
||
|
//remove every slots to that socket, so we won't delete receive signals
|
||
|
// from the old socket thinking they are from the new one
|
||
|
TQObject::disconnect( m_notifySocket , 0, this, 0 );
|
||
|
m_notifySocket->deleteLater(); //be sure it will be deleted
|
||
|
m_notifySocket=0L;
|
||
|
}
|
||
|
|
||
|
m_msgHandle.clear();
|
||
|
|
||
|
myself()->setOnlineStatus( MSNProtocol::protocol()->CNT );
|
||
|
|
||
|
|
||
|
m_notifySocket = new MSNNotifySocket( this, accountId() , m_password);
|
||
|
m_notifySocket->setUseHttpMethod( useHttpMethod() );
|
||
|
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( groupAdded( const TQString&, const TQString& ) ),
|
||
|
TQT_SLOT( slotGroupAdded( const TQString&, const TQString& ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( groupRenamed( const TQString&, const TQString& ) ),
|
||
|
TQT_SLOT( slotGroupRenamed( const TQString&, const TQString& ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( groupListed( const TQString&, const TQString& ) ),
|
||
|
TQT_SLOT( slotGroupAdded( const TQString&, const TQString& ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( groupRemoved( const TQString& ) ),
|
||
|
TQT_SLOT( slotGroupRemoved( const TQString& ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( contactList(const TQString&, const TQString&, const TQString&, uint, const TQString& ) ),
|
||
|
TQT_SLOT( slotContactListed(const TQString&, const TQString&, const TQString&, uint, const TQString& ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL(contactAdded(const TQString&, const TQString&, const TQString&, const TQString&, const TQString& ) ),
|
||
|
TQT_SLOT( slotContactAdded(const TQString&, const TQString&, const TQString&, const TQString&, const TQString& ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( contactRemoved(const TQString&, const TQString&, const TQString&, const TQString& ) ),
|
||
|
TQT_SLOT( slotContactRemoved(const TQString&, const TQString&, const TQString&, const TQString& ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( statusChanged( const Kopete::OnlineStatus & ) ),
|
||
|
TQT_SLOT( slotStatusChanged( const Kopete::OnlineStatus & ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( invitedToChat( const TQString&, const TQString&, const TQString&, const TQString&, const TQString& ) ),
|
||
|
TQT_SLOT( slotCreateChat( const TQString&, const TQString&, const TQString&, const TQString&, const TQString& ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( startChat( const TQString&, const TQString& ) ),
|
||
|
TQT_SLOT( slotCreateChat( const TQString&, const TQString& ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( socketClosed() ),
|
||
|
TQT_SLOT( slotNotifySocketClosed() ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( newContactList() ),
|
||
|
TQT_SLOT( slotNewContactList() ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( receivedNotificationServer(const TQString&, uint ) ),
|
||
|
TQT_SLOT(createNotificationServer(const TQString&, uint ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( hotmailSeted( bool ) ),
|
||
|
m_openInboxAction, TQT_SLOT( setEnabled( bool ) ) );
|
||
|
TQObject::connect( m_notifySocket, TQT_SIGNAL( errorMessage(int, const TQString& ) ),
|
||
|
TQT_SLOT( slotErrorMessageReceived(int, const TQString& ) ) );
|
||
|
|
||
|
m_notifySocket->setStatus( m_connectstatus );
|
||
|
m_notifySocket->connect(host, port);
|
||
|
}
|
||
|
|
||
|
void MSNAccount::disconnect()
|
||
|
{
|
||
|
if ( m_notifySocket )
|
||
|
m_notifySocket->disconnect();
|
||
|
}
|
||
|
|
||
|
TDEActionMenu * MSNAccount::actionMenu()
|
||
|
{
|
||
|
TDEActionMenu *m_actionMenu=Kopete::Account::actionMenu();
|
||
|
if ( isConnected() )
|
||
|
{
|
||
|
m_openInboxAction->setEnabled( true );
|
||
|
m_startChatAction->setEnabled( true );
|
||
|
m_changeDNAction->setEnabled( true );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_openInboxAction->setEnabled( false );
|
||
|
m_startChatAction->setEnabled( false );
|
||
|
m_changeDNAction->setEnabled( false );
|
||
|
}
|
||
|
|
||
|
m_actionMenu->popupMenu()->insertSeparator();
|
||
|
|
||
|
m_actionMenu->insert( m_changeDNAction );
|
||
|
m_actionMenu->insert( m_startChatAction );
|
||
|
|
||
|
// m_actionMenu->popupMenu()->insertSeparator();
|
||
|
|
||
|
m_actionMenu->insert( m_openInboxAction );
|
||
|
|
||
|
#if !defined NDEBUG
|
||
|
TDEActionMenu *debugMenu = new TDEActionMenu( "Debug", m_actionMenu );
|
||
|
debugMenu->insert( new TDEAction( i18n( "Send Raw C&ommand..." ), 0,
|
||
|
this, TQT_SLOT( slotDebugRawCommand() ), debugMenu, "m_debugRawCommand" ) );
|
||
|
m_actionMenu->popupMenu()->insertSeparator();
|
||
|
m_actionMenu->insert( debugMenu );
|
||
|
#endif
|
||
|
|
||
|
return m_actionMenu;
|
||
|
}
|
||
|
|
||
|
MSNNotifySocket *MSNAccount::notifySocket()
|
||
|
{
|
||
|
return m_notifySocket;
|
||
|
}
|
||
|
|
||
|
|
||
|
void MSNAccount::setOnlineStatus( const Kopete::OnlineStatus &status , const TQString &reason)
|
||
|
{
|
||
|
kdDebug( 14140 ) << k_funcinfo << status.description() << endl;
|
||
|
|
||
|
// HACK: When changing song, do don't anything while connected
|
||
|
if( reason.contains("[Music]") && ( status == MSNProtocol::protocol()->UNK || status == MSNProtocol::protocol()->CNT ) )
|
||
|
return;
|
||
|
|
||
|
// Only send personal message when logged.
|
||
|
if( m_notifySocket && m_notifySocket->isLogged() )
|
||
|
{
|
||
|
// Only update the personal/status message, don't change the online status
|
||
|
// since it's the same.
|
||
|
if( reason.contains("[Music]") )
|
||
|
{
|
||
|
TQString personalMessage = reason.section("[Music]", 1);
|
||
|
setPersonalMessage( MSNProtocol::PersonalMessageMusic, personalMessage );
|
||
|
|
||
|
// Don't send un-needed status change.
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
setPersonalMessage( MSNProtocol::PersonalMessageNormal, reason );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(status.status()== Kopete::OnlineStatus::Offline)
|
||
|
disconnect();
|
||
|
else if ( m_notifySocket )
|
||
|
{
|
||
|
m_notifySocket->setStatus( status );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_connectstatus = status;
|
||
|
connect();
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotStartChat()
|
||
|
{
|
||
|
|
||
|
bool ok;
|
||
|
TQString handle = KInputDialog::getText( i18n( "Start Chat - MSN Plugin" ),
|
||
|
i18n( "Please enter the email address of the person with whom you want to chat:" ), TQString(), &ok ).lower();
|
||
|
if ( ok )
|
||
|
{
|
||
|
if ( MSNProtocol::validContactId( handle ) )
|
||
|
{
|
||
|
if ( !contacts()[ handle ] )
|
||
|
addContact( handle, handle, 0L, Kopete::Account::Temporary );
|
||
|
|
||
|
contacts()[ handle ]->execute();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget(), KMessageBox::Sorry,
|
||
|
i18n( "<qt>You must enter a valid email address.</qt>" ), i18n( "MSN Plugin" ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotDebugRawCommand()
|
||
|
{
|
||
|
#if !defined NDEBUG
|
||
|
if ( !isConnected() )
|
||
|
return;
|
||
|
|
||
|
MSNDebugRawCmdDlg *dlg = new MSNDebugRawCmdDlg( 0L );
|
||
|
int result = dlg->exec();
|
||
|
if ( result == TQDialog::Accepted && m_notifySocket )
|
||
|
{
|
||
|
m_notifySocket->sendCommand( dlg->command(), dlg->params(),
|
||
|
dlg->addId(), dlg->msg().replace( "\n", "\r\n" ).utf8() );
|
||
|
}
|
||
|
delete dlg;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotChangePublicName()
|
||
|
{
|
||
|
if ( !isConnected() )
|
||
|
{
|
||
|
return;
|
||
|
//TODO: change it anyway, and sync at the next connection
|
||
|
}
|
||
|
|
||
|
bool ok;
|
||
|
TQString name = KInputDialog::getText( i18n( "Change Display Name - MSN Plugin" ),
|
||
|
i18n( "Enter the new display name by which you want to be visible to your friends on MSN:" ),
|
||
|
myself()->property( Kopete::Global::Properties::self()->nickName()).value().toString(), &ok );
|
||
|
|
||
|
if ( ok )
|
||
|
{
|
||
|
if ( name.length() > 387 )
|
||
|
{
|
||
|
KMessageBox::error( Kopete::UI::Global::mainWidget(),
|
||
|
i18n( "<qt>The display name you entered is too long. Please use a shorter name.\n"
|
||
|
"Your display name has <b>not</b> been changed.</qt>" ),
|
||
|
i18n( "Change Display Name - MSN Plugin" ) );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
setPublicName( name );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void MSNAccount::slotOpenInbox()
|
||
|
{
|
||
|
if ( m_notifySocket )
|
||
|
m_notifySocket->slotOpenInbox();
|
||
|
}
|
||
|
|
||
|
|
||
|
void MSNAccount::slotNotifySocketClosed()
|
||
|
{
|
||
|
kdDebug( 14140 ) << k_funcinfo << endl;
|
||
|
|
||
|
Kopete::Account::DisconnectReason reason=(Kopete::Account::DisconnectReason)(m_notifySocket->disconnectReason());
|
||
|
m_notifySocket->deleteLater();
|
||
|
m_notifySocket = 0l;
|
||
|
myself()->setOnlineStatus( MSNProtocol::protocol()->FLN );
|
||
|
setAllContactsStatus( MSNProtocol::protocol()->FLN );
|
||
|
disconnected(reason);
|
||
|
|
||
|
|
||
|
if(reason == Kopete::Account::OtherClient)
|
||
|
{ //close all chat sessions, so new message will arive to the other client.
|
||
|
|
||
|
TQValueList<Kopete::ChatSession*> sessions = Kopete::ChatSessionManager::self()->sessions();
|
||
|
TQValueList<Kopete::ChatSession*>::Iterator it;
|
||
|
for (it=sessions.begin() ; it != sessions.end() ; it++ )
|
||
|
{
|
||
|
MSNChatSession *msnCS = dynamic_cast<MSNChatSession *>( *it );
|
||
|
if ( msnCS && msnCS->account() == this )
|
||
|
{
|
||
|
msnCS->slotCloseSession();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
else if ( state == 0x10 ) // connection died unexpectedly
|
||
|
{
|
||
|
KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget(), KMessageBox::Error , i18n( "The connection with the MSN server was lost unexpectedly.\n"
|
||
|
"If you cannot reconnect now, the server might be down. In that case, please try again later." ),
|
||
|
i18n( "Connection Lost - MSN Plugin" ), KMessageBox::Notify );
|
||
|
}
|
||
|
#endif
|
||
|
m_msgHandle.clear();
|
||
|
// kdDebug( 14140 ) << "MSNAccount::slotNotifySocketClosed - done" << endl;
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotStatusChanged( const Kopete::OnlineStatus &status )
|
||
|
{
|
||
|
// kdDebug( 14140 ) << k_funcinfo << status.internalStatus() << endl;
|
||
|
myself()->setOnlineStatus( status );
|
||
|
|
||
|
if(m_newContactList)
|
||
|
{
|
||
|
m_newContactList=false;
|
||
|
|
||
|
TQDictIterator<Kopete::Contact> it( contacts() );
|
||
|
for ( ; it.current(); ++it )
|
||
|
{
|
||
|
MSNContact *c = static_cast<MSNContact *>( *it );
|
||
|
if(c && c->isDeleted() && c->metaContact() && !c->metaContact()->isTemporary() && c!=myself())
|
||
|
{
|
||
|
if(c->serverGroups().isEmpty())
|
||
|
{ //the contact is new, add it on the server
|
||
|
c->setOnlineStatus( MSNProtocol::protocol()->FLN );
|
||
|
addContactServerside( c->contactId() , c->metaContact()->groups() );
|
||
|
}
|
||
|
else //the contact had been deleted, remove it.
|
||
|
{
|
||
|
c->deleteLater();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void MSNAccount::slotPersonalMessageChanged( const TQString& personalMessage )
|
||
|
{
|
||
|
TQString oldPersonalMessage=myself()->property(MSNProtocol::protocol()->propPersonalMessage).value().toString() ;
|
||
|
if ( personalMessage != oldPersonalMessage )
|
||
|
{
|
||
|
myself()->setProperty( MSNProtocol::protocol()->propPersonalMessage, personalMessage );
|
||
|
configGroup()->writeEntry( "personalMessage" , personalMessage );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::setPublicName( const TQString &publicName )
|
||
|
{
|
||
|
if ( m_notifySocket )
|
||
|
{
|
||
|
m_notifySocket->changePublicName( publicName, TQString() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::setPersonalMessage( MSNProtocol::PersonalMessageType type, const TQString &personalMessage )
|
||
|
{
|
||
|
if ( m_notifySocket )
|
||
|
{
|
||
|
m_notifySocket->changePersonalMessage( type, personalMessage );
|
||
|
}
|
||
|
/* Eh, if we can't change the display name, don't let make the user think it has changed
|
||
|
else if(type == MSNProtocol::PersonalMessageNormal) // Normal personalMessage, not a dynamic one that need formatting.
|
||
|
{
|
||
|
slotPersonalMessageChanged( personalMessage );
|
||
|
}*/
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotGroupAdded( const TQString& groupName, const TQString &groupGuid )
|
||
|
{
|
||
|
if ( m_groupList.contains( groupGuid ) )
|
||
|
{
|
||
|
// Group can already be in the list since the idle timer does a 'List Groups'
|
||
|
// command. Simply return, don't issue a warning.
|
||
|
// kdDebug( 14140 ) << k_funcinfo << "Group " << groupName << " already in list, skipped." << endl;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//--------- Find the appropriate Kopete::Group, or create one ---------//
|
||
|
TQPtrList<Kopete::Group> groupList = Kopete::ContactList::self()->groups();
|
||
|
Kopete::Group *fallBack = 0L;
|
||
|
|
||
|
//check if we have one in the old group list. if yes, update the id translate map.
|
||
|
for(TQMap<TQString, Kopete::Group*>::Iterator it=m_oldGroupList.begin() ; it != m_oldGroupList.end() ; ++it )
|
||
|
{
|
||
|
Kopete::Group *g=it.data();
|
||
|
if (g && g->pluginData( protocol(), accountId() + " displayName" ) == groupName &&
|
||
|
g->pluginData( protocol(), accountId() + " id" ).isEmpty() )
|
||
|
{ //it has the same name! we got it. (and it is not yet an msn group)
|
||
|
fallBack=g;
|
||
|
/*if ( g->displayName() != groupName )
|
||
|
{
|
||
|
// The displayName was changed in Kopete while we were offline
|
||
|
// FIXME: update the server right now
|
||
|
}*/
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(!fallBack)
|
||
|
{
|
||
|
//it's certenly a new group ! search if one already exist with the same displayname.
|
||
|
for ( Kopete::Group *g = groupList.first(); g; g = groupList.next() )
|
||
|
{
|
||
|
/* --This has been replaced by the loop right before.
|
||
|
if ( !g->pluginData( protocol(), accountId() + " id" ).isEmpty() )
|
||
|
{
|
||
|
if ( g->pluginData( protocol(), accountId() + " id" ).toUInt() == groupNumber )
|
||
|
{
|
||
|
m_groupList.insert( groupNumber, g );
|
||
|
TQString oldGroupName;
|
||
|
if ( g->pluginData( protocol(), accountId() + " displayName" ) != groupName )
|
||
|
{
|
||
|
// The displayName of the group has been modified by another client
|
||
|
slotGroupRenamed( groupName, groupNumber );
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
else {*/
|
||
|
if ( g->displayName() == groupName && (groupGuid.isEmpty()|| g->type()==Kopete::Group::Normal) &&
|
||
|
g->pluginData( protocol(), accountId() + " id" ).isEmpty() )
|
||
|
{
|
||
|
fallBack = g;
|
||
|
kdDebug( 14140 ) << k_funcinfo << "We didn't found the group " << groupName <<" in the old MSN group. But kopete has already one with the same name." << endl;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !fallBack )
|
||
|
{
|
||
|
if( groupGuid.isEmpty() )
|
||
|
{ // The group #0 is an unremovable group. his default name is "~" ,
|
||
|
// but the official client rename it i18n("others contact") at the first
|
||
|
// connection.
|
||
|
// In many case, the users don't use that group as a real group, or just as
|
||
|
// a group to put all contact that are not sorted.
|
||
|
fallBack = Kopete::Group::topLevel();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fallBack = new Kopete::Group( groupName );
|
||
|
Kopete::ContactList::self()->addGroup( fallBack );
|
||
|
kdDebug( 14140 ) << k_funcinfo << "We didn't found the group " << groupName <<" So we're creating a new one." << endl;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fallBack->setPluginData( protocol(), accountId() + " id", groupGuid );
|
||
|
fallBack->setPluginData( protocol(), accountId() + " displayName", groupName );
|
||
|
m_groupList.insert( groupGuid, fallBack );
|
||
|
|
||
|
// We have pending groups that we need add a contact to
|
||
|
if ( tmp_addToNewGroup.contains(groupName) )
|
||
|
{
|
||
|
TQStringList list=tmp_addToNewGroup[groupName];
|
||
|
for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it )
|
||
|
{
|
||
|
TQString contactId = *it;
|
||
|
kdDebug( 14140 ) << k_funcinfo << "Adding to new group: " << contactId << endl;
|
||
|
MSNContact *c = static_cast<MSNContact *>(contacts()[contactId]);
|
||
|
if(c && c->hasProperty(MSNProtocol::protocol()->propGuid.key()) )
|
||
|
notifySocket()->addContact( contactId, MSNProtocol::FL, TQString(), c->guid(), groupGuid );
|
||
|
else
|
||
|
{
|
||
|
// If we get to here, we're currently adding a new contact, add the groupGUID to the groupList
|
||
|
// to add when contact will be added to contactlist.
|
||
|
if( tmp_addNewContactToGroup.contains( contactId ) )
|
||
|
tmp_addNewContactToGroup[contactId].append(groupGuid);
|
||
|
else
|
||
|
tmp_addNewContactToGroup.insert(contactId, TQStringList(groupGuid) );
|
||
|
}
|
||
|
}
|
||
|
tmp_addToNewGroup.remove(groupName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotGroupRenamed( const TQString &groupGuid, const TQString& groupName )
|
||
|
{
|
||
|
if ( m_groupList.contains( groupGuid ) )
|
||
|
{
|
||
|
m_groupList[ groupGuid ]->setPluginData( protocol(), accountId() + " id", groupGuid );
|
||
|
m_groupList[ groupGuid ]->setPluginData( protocol(), accountId() + " displayName", groupName );
|
||
|
m_groupList[ groupGuid ]->setDisplayName( groupName );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
slotGroupAdded( groupName, groupGuid );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotGroupRemoved( const TQString& groupGuid )
|
||
|
{
|
||
|
if ( m_groupList.contains( groupGuid ) )
|
||
|
{
|
||
|
m_groupList[ groupGuid ]->setPluginData( protocol(), TQMap<TQString,TQString>() );
|
||
|
m_groupList.remove( groupGuid );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::addGroup( const TQString &groupName, const TQString& contactToAdd )
|
||
|
{
|
||
|
if ( !contactToAdd.isNull() )
|
||
|
{
|
||
|
if( tmp_addToNewGroup.contains(groupName) )
|
||
|
{
|
||
|
tmp_addToNewGroup[groupName].append(contactToAdd);
|
||
|
//A group with the same name is about to be added,
|
||
|
// we don't need to add a second group with the same name
|
||
|
kdDebug( 14140 ) << k_funcinfo << "no need to re-add " << groupName << " for " << contactToAdd << endl;
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tmp_addToNewGroup.insert(groupName,TQStringList(contactToAdd));
|
||
|
kdDebug( 14140 ) << k_funcinfo << "preparing to add " << groupName << " for " << contactToAdd << endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_notifySocket )
|
||
|
m_notifySocket->addGroup( groupName );
|
||
|
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotKopeteGroupRenamed( Kopete::Group *g )
|
||
|
{
|
||
|
if ( notifySocket() && g->type() == Kopete::Group::Normal )
|
||
|
{
|
||
|
if ( !g->pluginData( protocol(), accountId() + " id" ).isEmpty() &&
|
||
|
g->displayName() != g->pluginData( protocol(), accountId() + " displayName" ) &&
|
||
|
m_groupList.contains( g->pluginData( protocol(), accountId() + " id" ) ) )
|
||
|
{
|
||
|
notifySocket()->renameGroup( g->displayName(), g->pluginData( protocol(), accountId() + " id" ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotKopeteGroupRemoved( Kopete::Group *g )
|
||
|
{
|
||
|
//The old gorup list is only used whe syncing the contactlist.
|
||
|
//We can assume the contactlist is already fully synced at this time.
|
||
|
//The group g is maybe in the oldGroupList. We remove everithing since
|
||
|
//we don't need it anymore, no need to search it
|
||
|
m_oldGroupList.clear();
|
||
|
|
||
|
|
||
|
if ( !g->pluginData( protocol(), accountId() + " id" ).isEmpty() )
|
||
|
{
|
||
|
TQString groupGuid = g->pluginData( protocol(), accountId() + " id" );
|
||
|
if ( !m_groupList.contains( groupGuid ) )
|
||
|
{
|
||
|
// the group is maybe already removed in the server
|
||
|
slotGroupRemoved( groupGuid );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//this is also done later, but he have to do it now!
|
||
|
// (in slotGroupRemoved)
|
||
|
m_groupList.remove(groupGuid);
|
||
|
|
||
|
if ( groupGuid.isEmpty() )
|
||
|
{
|
||
|
// the group #0 can't be deleted
|
||
|
// then we set it as the top-level group
|
||
|
if ( g->type() == Kopete::Group::TopLevel )
|
||
|
return;
|
||
|
|
||
|
Kopete::Group::topLevel()->setPluginData( protocol(), accountId() + " id", "" );
|
||
|
Kopete::Group::topLevel()->setPluginData( protocol(), accountId() + " displayName", g->pluginData( protocol(), accountId() + " displayName" ) );
|
||
|
g->setPluginData( protocol(), accountId() + " id", TQString() ); // the group should be soon deleted, but make sure
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( m_notifySocket )
|
||
|
{
|
||
|
bool still_have_contact=false;
|
||
|
// if contact are contains only in the group we are removing, abort the
|
||
|
TQDictIterator<Kopete::Contact> it( contacts() );
|
||
|
for ( ; it.current(); ++it )
|
||
|
{
|
||
|
MSNContact *c = static_cast<MSNContact *>( it.current() );
|
||
|
if ( c && c->serverGroups().contains( groupGuid ) )
|
||
|
{
|
||
|
/** don't do that becasue theses may already have been sent
|
||
|
m_notifySocket->removeContact( c->contactId(), groupNumber, MSNProtocol::FL );
|
||
|
*/
|
||
|
still_have_contact=true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if(!still_have_contact)
|
||
|
m_notifySocket->removeGroup( groupGuid );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotNewContactList()
|
||
|
{
|
||
|
m_oldGroupList=m_groupList;
|
||
|
for(TQMap<TQString, Kopete::Group*>::Iterator it=m_oldGroupList.begin() ; it != m_oldGroupList.end() ; ++it )
|
||
|
{ //they are about to be changed
|
||
|
if(it.data())
|
||
|
it.data()->setPluginData( protocol(), accountId() + " id", TQString() );
|
||
|
}
|
||
|
|
||
|
m_allowList.clear();
|
||
|
m_blockList.clear();
|
||
|
m_reverseList.clear();
|
||
|
m_groupList.clear();
|
||
|
TDEConfigGroup *config=configGroup();
|
||
|
config->writeEntry( "blockList" , TQString() ) ;
|
||
|
config->writeEntry( "allowList" , TQString() );
|
||
|
config->writeEntry( "reverseList" , TQString() );
|
||
|
|
||
|
// clear all date information which will be received.
|
||
|
// if the information is not anymore on the server, it will not be received
|
||
|
TQDictIterator<Kopete::Contact> it( contacts() );
|
||
|
for ( ; it.current(); ++it )
|
||
|
{
|
||
|
MSNContact *c = static_cast<MSNContact *>( *it );
|
||
|
c->setBlocked( false );
|
||
|
c->setAllowed( false );
|
||
|
c->setReversed( false );
|
||
|
c->setDeleted( true );
|
||
|
c->setInfo( "PHH", TQString() );
|
||
|
c->setInfo( "PHW", TQString() );
|
||
|
c->setInfo( "PHM", TQString() );
|
||
|
c->removeProperty( MSNProtocol::protocol()->propGuid );
|
||
|
}
|
||
|
m_newContactList=true;
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotContactListed( const TQString& handle, const TQString& publicName, const TQString &contactGuid, uint lists, const TQString& groups )
|
||
|
{
|
||
|
// On empty lists handle might be empty, ignore that
|
||
|
// ignore also the myself contact.
|
||
|
if ( handle.isEmpty() || handle==accountId())
|
||
|
return;
|
||
|
|
||
|
MSNContact *c = static_cast<MSNContact *>( contacts()[ handle ] );
|
||
|
|
||
|
if ( lists & 1 ) // FL
|
||
|
{
|
||
|
TQStringList contactGroups = TQStringList::split( ",", groups, false );
|
||
|
if ( c )
|
||
|
{
|
||
|
if( !c->metaContact() )
|
||
|
{
|
||
|
kdWarning( 14140 ) << k_funcinfo << "the contact " << c->contactId() << " has no meta contact" <<endl;
|
||
|
Kopete::MetaContact *metaContact = new Kopete::MetaContact();
|
||
|
|
||
|
c->setMetaContact(metaContact);
|
||
|
Kopete::ContactList::self()->addMetaContact( metaContact );
|
||
|
}
|
||
|
|
||
|
// Contact exists, update data.
|
||
|
// Merging difference between server contact list and Kopete::Contact's contact list into MetaContact's contact-list
|
||
|
c->setOnlineStatus( MSNProtocol::protocol()->FLN );
|
||
|
if(!publicName.isEmpty() && publicName!=handle)
|
||
|
c->setProperty( Kopete::Global::Properties::self()->nickName() , publicName );
|
||
|
else
|
||
|
c->removeProperty( Kopete::Global::Properties::self()->nickName() );
|
||
|
c->setProperty( MSNProtocol::protocol()->propGuid, contactGuid);
|
||
|
|
||
|
const TQMap<TQString, Kopete::Group *> oldServerGroups = c->serverGroups();
|
||
|
c->clearServerGroups();
|
||
|
for ( TQStringList::ConstIterator it = contactGroups.begin(); it != contactGroups.end(); ++it )
|
||
|
{
|
||
|
TQString newServerGroupID = *it;
|
||
|
if(m_groupList.contains(newServerGroupID))
|
||
|
{
|
||
|
Kopete::Group *newServerGroup=m_groupList[ newServerGroupID ] ;
|
||
|
c->contactAddedToGroup( newServerGroupID, newServerGroup );
|
||
|
if( !c->metaContact()->groups().contains(newServerGroup) )
|
||
|
{
|
||
|
// The contact has been added in a group by another client
|
||
|
c->metaContact()->addToGroup( newServerGroup );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for ( TQMap<TQString, Kopete::Group *>::ConstIterator it = oldServerGroups.begin(); it != oldServerGroups.end(); ++it )
|
||
|
{
|
||
|
Kopete::Group *old_group=m_oldGroupList[it.key()];
|
||
|
if(old_group)
|
||
|
{
|
||
|
TQString oldnewID=old_group->pluginData(protocol() , accountId() +" id");
|
||
|
if ( !oldnewID.isEmpty() && contactGroups.contains( oldnewID ) )
|
||
|
continue; //ok, it's correctn no need to do anything.
|
||
|
|
||
|
c->metaContact()->removeFromGroup( old_group );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
c->setDeleted(false);
|
||
|
|
||
|
// Update server if the contact has been moved to another group while MSN was offline
|
||
|
c->sync();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Kopete::MetaContact *metaContact = new Kopete::MetaContact();
|
||
|
|
||
|
c = new MSNContact( this, handle, metaContact );
|
||
|
c->setDeleted(true); //we don't want to sync
|
||
|
c->setOnlineStatus( MSNProtocol::protocol()->FLN );
|
||
|
if(!publicName.isEmpty() && publicName!=handle)
|
||
|
c->setProperty( Kopete::Global::Properties::self()->nickName() , publicName );
|
||
|
else
|
||
|
c->removeProperty( Kopete::Global::Properties::self()->nickName() );
|
||
|
c->setProperty( MSNProtocol::protocol()->propGuid, contactGuid );
|
||
|
|
||
|
for ( TQStringList::Iterator it = contactGroups.begin();
|
||
|
it != contactGroups.end(); ++it )
|
||
|
{
|
||
|
TQString groupGuid = *it;
|
||
|
if(m_groupList.contains(groupGuid))
|
||
|
{
|
||
|
c->contactAddedToGroup( groupGuid, m_groupList[ groupGuid ] );
|
||
|
metaContact->addToGroup( m_groupList[ groupGuid ] );
|
||
|
}
|
||
|
}
|
||
|
Kopete::ContactList::self()->addMetaContact( metaContact );
|
||
|
|
||
|
c->setDeleted(false);
|
||
|
}
|
||
|
}
|
||
|
else //the contact is _not_ in the FL, it has been removed
|
||
|
{
|
||
|
if(c)
|
||
|
{
|
||
|
c->setOnlineStatus( static_cast<MSNProtocol*>(protocol())->UNK );
|
||
|
c->clearServerGroups();
|
||
|
//TODO: display a message and suggest to remove the contact.
|
||
|
// but i fear a simple messageBox QuestionYesNo here gives a nice crash.
|
||
|
//delete ct;
|
||
|
}
|
||
|
}
|
||
|
if ( lists & 2 )
|
||
|
slotContactAdded( handle, "AL", publicName, TQString(), TQString() );
|
||
|
else if(c)
|
||
|
c->setAllowed(false);
|
||
|
if ( lists & 4 )
|
||
|
slotContactAdded( handle, "BL", publicName, TQString(), TQString() );
|
||
|
else if(c)
|
||
|
c->setBlocked(false);
|
||
|
if ( lists & 8 )
|
||
|
slotContactAdded( handle, "RL", publicName, TQString(), TQString() );
|
||
|
else if(c)
|
||
|
c->setReversed(false);
|
||
|
if ( lists & 16 ) // This contact is on the pending list. Add to the reverse list and delete from the pending list
|
||
|
{
|
||
|
notifySocket()->addContact( handle, MSNProtocol::RL, TQString(), TQString(), TQString() );
|
||
|
notifySocket()->removeContact( handle, MSNProtocol::PL, TQString(), TQString() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotContactAdded( const TQString& handle, const TQString& list, const TQString& publicName, const TQString& contactGuid, const TQString &groupGuid )
|
||
|
{
|
||
|
if ( list == "FL" )
|
||
|
{
|
||
|
bool new_contact = false;
|
||
|
if ( !contacts()[ handle ] )
|
||
|
{
|
||
|
new_contact = true;
|
||
|
|
||
|
Kopete::MetaContact *m= m_addWizard_metaContact ? m_addWizard_metaContact : new Kopete::MetaContact();
|
||
|
|
||
|
MSNContact *c = new MSNContact( this, handle, m );
|
||
|
if(!publicName.isEmpty() && publicName!=handle)
|
||
|
c->setProperty( Kopete::Global::Properties::self()->nickName() , publicName );
|
||
|
else
|
||
|
c->removeProperty( Kopete::Global::Properties::self()->nickName() );
|
||
|
c->setProperty( MSNProtocol::protocol()->propGuid, contactGuid );
|
||
|
// Add the new contact to the group he belongs.
|
||
|
if ( tmp_addNewContactToGroup.contains(handle) )
|
||
|
{
|
||
|
TQStringList list = tmp_addNewContactToGroup[handle];
|
||
|
for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it )
|
||
|
{
|
||
|
TQString groupGuid = *it;
|
||
|
|
||
|
// If the group didn't exist yet (yay for async operations), don't add the contact to the group
|
||
|
// Let slotGroupAdded do it.
|
||
|
if( m_groupList.contains(groupGuid) )
|
||
|
{
|
||
|
kdDebug( 14140 ) << k_funcinfo << "Adding " << handle << " to group: " << groupGuid << endl;
|
||
|
notifySocket()->addContact( handle, MSNProtocol::FL, TQString(), contactGuid, groupGuid );
|
||
|
|
||
|
c->contactAddedToGroup( groupGuid, m_groupList[ groupGuid ] );
|
||
|
|
||
|
m->addToGroup( m_groupList[ groupGuid ] );
|
||
|
|
||
|
}
|
||
|
if ( !m_addWizard_metaContact )
|
||
|
{
|
||
|
Kopete::ContactList::self()->addMetaContact( m );
|
||
|
}
|
||
|
}
|
||
|
tmp_addNewContactToGroup.remove(handle);
|
||
|
}
|
||
|
|
||
|
c->setOnlineStatus( MSNProtocol::protocol()->FLN );
|
||
|
|
||
|
m_addWizard_metaContact = 0L;
|
||
|
}
|
||
|
if ( !new_contact )
|
||
|
{
|
||
|
// Contact has been added to a group
|
||
|
MSNContact *c = findContactByGuid(contactGuid);
|
||
|
if(c != 0L)
|
||
|
{
|
||
|
// Make sure that the contact has always his contactGUID.
|
||
|
if( !c->hasProperty(MSNProtocol::protocol()->propGuid.key()) )
|
||
|
c->setProperty( MSNProtocol::protocol()->propGuid, contactGuid );
|
||
|
|
||
|
if ( c->onlineStatus() == MSNProtocol::protocol()->UNK )
|
||
|
c->setOnlineStatus( MSNProtocol::protocol()->FLN );
|
||
|
|
||
|
if ( c->metaContact() && c->metaContact()->isTemporary() )
|
||
|
c->metaContact()->setTemporary( false, m_groupList.contains( groupGuid ) ? m_groupList[ groupGuid ] : 0L );
|
||
|
else
|
||
|
{
|
||
|
if(m_groupList.contains(groupGuid))
|
||
|
{
|
||
|
if( c->metaContact() )
|
||
|
c->metaContact()->addToGroup( m_groupList[groupGuid] );
|
||
|
c->contactAddedToGroup( groupGuid, m_groupList[ groupGuid ] );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !handle.isEmpty() && !m_allowList.contains( handle ) && !m_blockList.contains( handle ) )
|
||
|
{
|
||
|
kdDebug(14140) << k_funcinfo << "Trying to add contact to AL. " << endl;
|
||
|
notifySocket()->addContact(handle, MSNProtocol::AL, TQString(), TQString(), TQString() );
|
||
|
}
|
||
|
}
|
||
|
else if ( list == "BL" )
|
||
|
{
|
||
|
if ( contacts()[ handle ] )
|
||
|
static_cast<MSNContact *>( contacts()[ handle ] )->setBlocked( true );
|
||
|
if ( !m_blockList.contains( handle ) )
|
||
|
{
|
||
|
m_blockList.append( handle );
|
||
|
configGroup()->writeEntry( "blockList" , m_blockList ) ;
|
||
|
}
|
||
|
}
|
||
|
else if ( list == "AL" )
|
||
|
{
|
||
|
if ( contacts()[ handle ] )
|
||
|
static_cast<MSNContact *>( contacts()[ handle ] )->setAllowed( true );
|
||
|
if ( !m_allowList.contains( handle ) )
|
||
|
{
|
||
|
m_allowList.append( handle );
|
||
|
configGroup()->writeEntry( "allowList" , m_allowList ) ;
|
||
|
}
|
||
|
}
|
||
|
else if ( list == "RL" )
|
||
|
{
|
||
|
// search for new Contacts
|
||
|
Kopete::Contact *ct=contacts()[ handle ];
|
||
|
if ( !ct || !ct->metaContact() || ct->metaContact()->isTemporary() )
|
||
|
{
|
||
|
// Users in the allow list or block list now never trigger the
|
||
|
// 'new user' dialog, which makes it impossible to add those here.
|
||
|
// Not necessarily bad, but the usability effects need more thought
|
||
|
// before I declare it good :- )
|
||
|
if ( !m_allowList.contains( handle ) && !m_blockList.contains( handle ) )
|
||
|
{
|
||
|
TQString nick; //in most case, the public name is not know
|
||
|
if(publicName!=handle) // so we don't whos it if it is not know
|
||
|
nick=publicName;
|
||
|
Kopete::UI::ContactAddedNotifyDialog *dialog=
|
||
|
new Kopete::UI::ContactAddedNotifyDialog( handle,nick,this,
|
||
|
Kopete::UI::ContactAddedNotifyDialog::InfoButton );
|
||
|
TQObject::connect(dialog,TQT_SIGNAL(applyClicked(const TQString&)),
|
||
|
this,TQT_SLOT(slotContactAddedNotifyDialogClosed(const TQString& )));
|
||
|
dialog->show();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
static_cast<MSNContact *>( ct )->setReversed( true );
|
||
|
}
|
||
|
m_reverseList.append( handle );
|
||
|
configGroup()->writeEntry( "reverseList" , m_reverseList ) ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotContactRemoved( const TQString& handle, const TQString& list, const TQString& contactGuid, const TQString& groupGuid )
|
||
|
{
|
||
|
kdDebug( 14140 ) << k_funcinfo << "handle: " << handle << " list: " << list << " contact-uid: " << contactGuid << endl;
|
||
|
MSNContact *c=static_cast<MSNContact *>( contacts()[ handle ] );
|
||
|
if ( list == "BL" )
|
||
|
{
|
||
|
m_blockList.remove( handle );
|
||
|
configGroup()->writeEntry( "blockList" , m_blockList ) ;
|
||
|
if ( !m_allowList.contains( handle ) )
|
||
|
notifySocket()->addContact( handle, MSNProtocol::AL, TQString(), TQString(), TQString() );
|
||
|
|
||
|
if(c)
|
||
|
c->setBlocked( false );
|
||
|
}
|
||
|
else if ( list == "AL" )
|
||
|
{
|
||
|
m_allowList.remove( handle );
|
||
|
configGroup()->writeEntry( "allowList" , m_allowList ) ;
|
||
|
if ( !m_blockList.contains( handle ) )
|
||
|
notifySocket()->addContact( handle, MSNProtocol::BL, TQString(), TQString(), TQString() );
|
||
|
|
||
|
if(c)
|
||
|
c->setAllowed( false );
|
||
|
}
|
||
|
else if ( list == "RL" )
|
||
|
{
|
||
|
m_reverseList.remove( handle );
|
||
|
configGroup()->writeEntry( "reverseList" , m_reverseList ) ;
|
||
|
|
||
|
if ( c )
|
||
|
{
|
||
|
// Contact is removed from the reverse list
|
||
|
// only MSN can do this, so this is currently not supported
|
||
|
c->setReversed( false );
|
||
|
/*
|
||
|
InfoWidget *info = new InfoWidget( 0 );
|
||
|
info->title->setText( "<b>" + i18n( "Contact removed!" ) +"</b>" );
|
||
|
TQString dummy;
|
||
|
dummy = "<center><b>" + imContact->getPublicName() + "( " +imContact->getHandle() +" )</b></center><br>";
|
||
|
dummy += i18n( "has removed you from his contact list!" ) + "<br>";
|
||
|
dummy += i18n( "This contact is now removed from your contact list" );
|
||
|
info->infoText->setText( dummy );
|
||
|
info->setCaption( "KMerlin - Info" );
|
||
|
info->show();
|
||
|
*/
|
||
|
}
|
||
|
}
|
||
|
else if ( list == "FL" )
|
||
|
{
|
||
|
// The FL list only use the contact GUID, use the contact referenced by the GUID.
|
||
|
MSNContact *contactRemoved = findContactByGuid(contactGuid);
|
||
|
TQStringList groupGuidList;
|
||
|
bool deleteContact = groupGuid.isEmpty() ? true : false; // Delete the contact when the group GUID is empty.
|
||
|
// Remove the contact from the contact list for all the group he is a member.
|
||
|
if( groupGuid.isEmpty() )
|
||
|
{
|
||
|
if(contactRemoved)
|
||
|
{
|
||
|
TQPtrList<Kopete::Group> groupList = contactRemoved->metaContact()->groups();
|
||
|
for( TQPtrList<Kopete::Group>::Iterator it = groupList.begin(); it != groupList.end(); ++it )
|
||
|
{
|
||
|
Kopete::Group *group = *it;
|
||
|
if ( !group->pluginData( protocol(), accountId() + " id" ).isEmpty() )
|
||
|
{
|
||
|
groupGuidList.append( group->pluginData( protocol(), accountId() + " id" ) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
groupGuidList.append( groupGuid );
|
||
|
}
|
||
|
|
||
|
if( !groupGuidList.isEmpty() )
|
||
|
{
|
||
|
TQStringList::const_iterator stringIt;
|
||
|
for( stringIt = groupGuidList.begin(); stringIt != groupGuidList.end(); ++stringIt )
|
||
|
{
|
||
|
// Contact is removed from the FL list, remove it from the group
|
||
|
if(contactRemoved != 0L)
|
||
|
contactRemoved->contactRemovedFromGroup( *stringIt );
|
||
|
|
||
|
//check if the group is now empty to remove it
|
||
|
if ( m_notifySocket )
|
||
|
{
|
||
|
bool still_have_contact=false;
|
||
|
// if contact are contains only in the group we are removing, abort the
|
||
|
TQDictIterator<Kopete::Contact> it( contacts() );
|
||
|
for ( ; it.current(); ++it )
|
||
|
{
|
||
|
MSNContact *c2 = static_cast<MSNContact *>( it.current() );
|
||
|
if ( c2->serverGroups().contains( *stringIt ) )
|
||
|
{
|
||
|
still_have_contact=true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if(!still_have_contact)
|
||
|
m_notifySocket->removeGroup( *stringIt );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if(deleteContact && contactRemoved)
|
||
|
{
|
||
|
kdDebug(14140) << k_funcinfo << "Deleting the MSNContact " << contactRemoved->contactId() << endl;
|
||
|
contactRemoved->deleteLater();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotCreateChat( const TQString& address, const TQString& auth )
|
||
|
{
|
||
|
slotCreateChat( 0L, address, auth, m_msgHandle.first(), m_msgHandle.first() );
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotCreateChat( const TQString& ID, const TQString& address, const TQString& auth,
|
||
|
const TQString& handle_, const TQString& publicName )
|
||
|
{
|
||
|
TQString handle = handle_.lower();
|
||
|
|
||
|
if ( handle.isEmpty() )
|
||
|
{
|
||
|
// we have lost the handle?
|
||
|
kdDebug(14140) << k_funcinfo << "Impossible to open a chat session, I forgot the contact to invite" <<endl;
|
||
|
// forget it
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// kdDebug( 14140 ) << k_funcinfo <<"Creating chat for " << handle << endl;
|
||
|
|
||
|
if ( !contacts()[ handle ] )
|
||
|
addContact( handle, publicName, 0L, Kopete::Account::Temporary );
|
||
|
|
||
|
MSNContact *c = static_cast<MSNContact *>( contacts()[ handle ] );
|
||
|
|
||
|
if ( c && myself() )
|
||
|
{
|
||
|
// we can't use simply c->manager(true) here to get the manager, because this will re-open
|
||
|
// another chat session, and then, close this new one. We have to re-create the manager manualy.
|
||
|
MSNChatSession *manager = dynamic_cast<MSNChatSession*>( c->manager( Kopete::Contact::CannotCreate ) );
|
||
|
if(!manager)
|
||
|
{
|
||
|
Kopete::ContactPtrList chatmembers;
|
||
|
chatmembers.append(c);
|
||
|
manager = new MSNChatSession( protocol(), myself(), chatmembers );
|
||
|
}
|
||
|
|
||
|
manager->createChat( handle, address, auth, ID );
|
||
|
|
||
|
/**
|
||
|
* This code should open a chatwindow when a socket is open
|
||
|
* It has been disabled because pidgin open switchboeard too often
|
||
|
*
|
||
|
* the solution is to open the window only when the contact start typing
|
||
|
* see MSNChatSession::receivedTypingMsg
|
||
|
*
|
||
|
|
||
|
TDEGlobal::config()->setGroup( "MSN" );
|
||
|
bool notifyNewChat = TDEGlobal::config()->readBoolEntry( "NotifyNewChat", false );
|
||
|
if ( !ID.isEmpty() && notifyNewChat )
|
||
|
{
|
||
|
// this temporary message should open the window if they not exist
|
||
|
TQString body = i18n( "%1 has started a chat with you" ).arg( c->metaContact()->displayName() );
|
||
|
Kopete::Message tmpMsg = Kopete::Message( c, manager->members(), body, Kopete::Message::Internal, Kopete::Message::PlainText );
|
||
|
manager->appendMessage( tmpMsg );
|
||
|
}
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
if(!m_msgHandle.isEmpty())
|
||
|
m_msgHandle.pop_front();
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotStartChatSession( const TQString& handle )
|
||
|
{
|
||
|
// First create a message manager, because we might get an existing
|
||
|
// manager back, in which case we likely also have an active switchboard
|
||
|
// connection to reuse...
|
||
|
|
||
|
MSNContact *c = static_cast<MSNContact *>( contacts()[ handle ] );
|
||
|
// if ( isConnected() && c && myself() && handle != m_msnId )
|
||
|
if ( m_notifySocket && c && myself() && handle != accountId() )
|
||
|
{
|
||
|
if ( !c->manager(Kopete::Contact::CannotCreate) || !static_cast<MSNChatSession *>( c->manager( Kopete::Contact::CanCreate ) )->service() )
|
||
|
{
|
||
|
m_msgHandle.prepend(handle);
|
||
|
m_notifySocket->createChatSession();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotContactAddedNotifyDialogClosed(const TQString& handle)
|
||
|
{
|
||
|
const Kopete::UI::ContactAddedNotifyDialog *dialog =
|
||
|
dynamic_cast<const Kopete::UI::ContactAddedNotifyDialog *>(sender());
|
||
|
if(!dialog || !m_notifySocket)
|
||
|
return;
|
||
|
|
||
|
if(dialog->added())
|
||
|
{
|
||
|
Kopete::MetaContact *mc=dialog->addContact();
|
||
|
if(mc)
|
||
|
{ //if the contact has been added this way, it's because the other user added us.
|
||
|
// don't forgot to set the reversed flag (Bug 114400)
|
||
|
MSNContact *c=dynamic_cast<MSNContact*>(mc->contacts().first());
|
||
|
if(c && c->contactId() == handle )
|
||
|
{
|
||
|
c->setReversed( true );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !dialog->authorized() )
|
||
|
{
|
||
|
if ( m_allowList.contains( handle ) )
|
||
|
m_notifySocket->removeContact( handle, MSNProtocol::AL, TQString(), TQString() );
|
||
|
else if ( !m_blockList.contains( handle ) )
|
||
|
m_notifySocket->addContact( handle, MSNProtocol::BL, TQString(), TQString(), TQString() );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( m_blockList.contains( handle ) )
|
||
|
m_notifySocket->removeContact( handle, MSNProtocol::BL, TQString(), TQString() );
|
||
|
else if ( !m_allowList.contains( handle ) )
|
||
|
m_notifySocket->addContact( handle, MSNProtocol::AL, TQString(), TQString(), TQString() );
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotGlobalIdentityChanged( const TQString &key, const TQVariant &value )
|
||
|
{
|
||
|
if( !configGroup()->readBoolEntry("ExcludeGlobalIdentity", false) )
|
||
|
{
|
||
|
if(key == Kopete::Global::Properties::self()->nickName().key())
|
||
|
{
|
||
|
TQString oldNick = myself()->property( Kopete::Global::Properties::self()->nickName()).value().toString();
|
||
|
TQString newNick = value.toString();
|
||
|
|
||
|
if(newNick != oldNick)
|
||
|
{
|
||
|
setPublicName( value.toString() );
|
||
|
}
|
||
|
}
|
||
|
else if(key == Kopete::Global::Properties::self()->photo().key())
|
||
|
{
|
||
|
m_pictureFilename = value.toString();
|
||
|
kdDebug( 14140 ) << k_funcinfo << m_pictureFilename << endl;
|
||
|
resetPictureObject(false, true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MSNAccount::slotErrorMessageReceived( int type, const TQString &msg )
|
||
|
{
|
||
|
TQString caption = i18n( "MSN Plugin" );
|
||
|
|
||
|
// Use different notification type based on the error context.
|
||
|
switch(type)
|
||
|
{
|
||
|
case MSNSocket::ErrorConnectionLost:
|
||
|
{
|
||
|
Kopete::Utils::notifyConnectionLost( this, caption, msg );
|
||
|
break;
|
||
|
}
|
||
|
case MSNSocket::ErrorConnectionError:
|
||
|
{
|
||
|
Kopete::Utils::notifyConnectionError( this, caption, msg );
|
||
|
break;
|
||
|
}
|
||
|
case MSNSocket::ErrorCannotConnect:
|
||
|
{
|
||
|
Kopete::Utils::notifyCannotConnect( this );
|
||
|
break;
|
||
|
}
|
||
|
case MSNSocket::ErrorInformation:
|
||
|
{
|
||
|
KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget(), KMessageBox::Information, msg, caption );
|
||
|
break;
|
||
|
}
|
||
|
case MSNSocket::ErrorServerError:
|
||
|
default:
|
||
|
{
|
||
|
Kopete::Utils::notifyServerError( this, caption, msg );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool MSNAccount::createContact( const TQString &contactId, Kopete::MetaContact *metaContact )
|
||
|
{
|
||
|
if ( !metaContact->isTemporary() && m_notifySocket)
|
||
|
{
|
||
|
m_addWizard_metaContact = metaContact;
|
||
|
|
||
|
addContactServerside(contactId, metaContact->groups());
|
||
|
|
||
|
// FIXME: Find out if this contact was really added or not!
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// This is a temporary contact. ( a person who messaged us but is not on our conntact list.
|
||
|
// We don't want to create it on the server.Just create the local contact object and add it
|
||
|
// Or we are diconnected, and in that case, the contact will be added when connecting
|
||
|
MSNContact *newContact = new MSNContact( this, contactId, metaContact );
|
||
|
newContact->setDeleted(true);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void MSNAccount::addContactServerside(const TQString &contactId, TQPtrList<Kopete::Group> groupList)
|
||
|
{
|
||
|
// First of all, fill the temporary group list. The contact will be moved to his group(s).
|
||
|
// When we receive back his contact GUID(required to move a contact between groups)
|
||
|
for( Kopete::Group *group = groupList.first(); group; group = groupList.next() )
|
||
|
{
|
||
|
// TODO: It it time that libkopete generate a unique ID that contains protocols, account and contact id.
|
||
|
TQString groupId = group->pluginData( protocol(), accountId() + " id" );
|
||
|
// If the groupId is empty, that's mean the Kopete group is not on the MSN server.
|
||
|
if( !groupId.isEmpty() )
|
||
|
{
|
||
|
// Something got corrupted on contactlist.xml
|
||
|
if( !m_groupList.contains(groupId) )
|
||
|
{
|
||
|
// Clear the group plugin data.
|
||
|
group->setPluginData( protocol() , accountId() + " id" , TQString());
|
||
|
group->setPluginData( protocol() , accountId() + " displayName" , TQString());
|
||
|
kdDebug( 14140 ) << k_funcinfo << " Group " << group->displayName() << " marked with id #" << groupId << " does not seems to be anymore on the server" << endl;
|
||
|
|
||
|
// Add the group on MSN server, will fix the corruption.
|
||
|
kdDebug(14140) << k_funcinfo << "Fixing group corruption, re-adding " << group->displayName() << "to the server." << endl;
|
||
|
addGroup( group->displayName(), contactId);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Add the group that the contact belong to add it when we will receive the contact GUID.
|
||
|
if( tmp_addNewContactToGroup.contains( contactId ) )
|
||
|
tmp_addNewContactToGroup[contactId].append(groupId);
|
||
|
else
|
||
|
tmp_addNewContactToGroup.insert(contactId, TQStringList(groupId) );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( !group->displayName().isEmpty() && group->type() == Kopete::Group::Normal )
|
||
|
{
|
||
|
kdDebug(14140) << k_funcinfo << "Group not on MSN server, add it" << endl;
|
||
|
addGroup( group->displayName(), contactId );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// After add the contact to the top-level, it will be moved to required groups later.
|
||
|
kdDebug( 14140 ) << k_funcinfo << "Add the contact on the server " << endl;
|
||
|
m_notifySocket->addContact( contactId, MSNProtocol::FL, contactId, TQString(), TQString() );
|
||
|
}
|
||
|
|
||
|
MSNContact *MSNAccount::findContactByGuid(const TQString &contactGuid)
|
||
|
{
|
||
|
kdDebug(14140) << k_funcinfo << "Looking for " << contactGuid << endl;
|
||
|
TQDictIterator<Kopete::Contact> it( contacts() );
|
||
|
for ( ; it.current(); ++it )
|
||
|
{
|
||
|
MSNContact *c = dynamic_cast<MSNContact *>( it.current() );
|
||
|
|
||
|
if(c && c->guid() == contactGuid )
|
||
|
{
|
||
|
kdDebug(14140) << k_funcinfo << "OK found a contact. " << endl;
|
||
|
// Found the contact GUID
|
||
|
return c;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0L;
|
||
|
}
|
||
|
|
||
|
bool MSNAccount::isHotmail() const
|
||
|
{
|
||
|
if ( !m_openInboxAction )
|
||
|
return false;
|
||
|
return m_openInboxAction->isEnabled();
|
||
|
}
|
||
|
|
||
|
TQString MSNAccount::pictureUrl()
|
||
|
{
|
||
|
return m_pictureFilename;
|
||
|
}
|
||
|
|
||
|
void MSNAccount::setPictureUrl(const TQString &url)
|
||
|
{
|
||
|
m_pictureFilename = url;
|
||
|
}
|
||
|
|
||
|
TQString MSNAccount::pictureObject()
|
||
|
{
|
||
|
if(m_pictureObj.isNull())
|
||
|
resetPictureObject(true); //silent=true to keep infinite loop away
|
||
|
return m_pictureObj;
|
||
|
}
|
||
|
|
||
|
void MSNAccount::resetPictureObject(bool silent, bool force)
|
||
|
{
|
||
|
TQString old=m_pictureObj;
|
||
|
|
||
|
if(!configGroup()->readBoolEntry("exportCustomPicture") && !force)
|
||
|
{
|
||
|
m_pictureObj="";
|
||
|
myself()->removeProperty( Kopete::Global::Properties::self()->photo() );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Check if the picture is a 96x96 image, if not scale, crop and save.
|
||
|
TQImage picture(m_pictureFilename);
|
||
|
if(picture.isNull())
|
||
|
{
|
||
|
m_pictureObj="";
|
||
|
myself()->removeProperty( Kopete::Global::Properties::self()->photo() );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(picture.width() != 96 || picture.height() != 96)
|
||
|
{
|
||
|
// Save to a new location in msnpictures.
|
||
|
TQString newLocation( locateLocal( "appdata", "msnpictures/"+ KURL(m_pictureFilename).fileName().lower() ) );
|
||
|
|
||
|
// Scale and crop the picture.
|
||
|
picture = MSNProtocol::protocol()->scalePicture(picture);
|
||
|
|
||
|
// Use the cropped/scaled image now.
|
||
|
if(!picture.save(newLocation, "PNG"))
|
||
|
{
|
||
|
m_pictureObj="";
|
||
|
myself()->removeProperty( Kopete::Global::Properties::self()->photo() );
|
||
|
}
|
||
|
m_pictureFilename = newLocation;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TQFile pictFile( m_pictureFilename );
|
||
|
if(!pictFile.open(IO_ReadOnly))
|
||
|
{
|
||
|
m_pictureObj="";
|
||
|
myself()->removeProperty( Kopete::Global::Properties::self()->photo() );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TQByteArray ar=pictFile.readAll();
|
||
|
TQString sha1d= TQString((KCodecs::base64Encode(SHA1::hash(ar))));
|
||
|
|
||
|
TQString size=TQString::number( pictFile.size() );
|
||
|
TQString all= "Creator"+accountId()+"Size"+size+"Type3Locationkopete.tmpFriendlyAAA=SHA1D"+ sha1d;
|
||
|
m_pictureObj="<msnobj Creator=\"" + accountId() + "\" Size=\"" + size + "\" Type=\"3\" Location=\"kopete.tmp\" Friendly=\"AAA=\" SHA1D=\""+sha1d+"\" SHA1C=\""+ TQString(KCodecs::base64Encode(SHA1::hashString(all.utf8()))) +"\"/>";
|
||
|
myself()->setProperty( Kopete::Global::Properties::self()->photo() , m_pictureFilename );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(old!=m_pictureObj && isConnected() && m_notifySocket && !silent)
|
||
|
{
|
||
|
//update the msn pict
|
||
|
m_notifySocket->setStatus( myself()->onlineStatus() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#include "msnaccount.moc"
|
||
|
|
||
|
// vim: set noet ts=4 sts=4 sw=4:
|
||
|
|
||
|
|