/*
msnnotifysocket . cpp - Notify Socket for the MSN Protocol
Copyright ( c ) 2002 by Duncan Mac - Vicar Prett < duncan @ kde . org >
Copyright ( c ) 2002 - 2003 by Martijn Klingens < klingens @ kde . org >
Copyright ( c ) 2002 - 2005 by Olivier Goffart < ogoffart at kde . org >
Copyright ( c ) 2005 by Micha ë l Larouche < michael . larouche @ kdemail . net >
Copyright ( c ) 2005 by Gregg Edghill < gregg . edghill @ gmail . com >
Kopete ( c ) 2002 - 2005 by the Kopete developers < kopete - devel @ kde . org >
Portions taken from
KMerlin ( c ) 2001 by Olaf Lueg < olueg @ olsd . de >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 "msnnotifysocket.h"
# include "msncontact.h"
# include "msnaccount.h"
# include "msnsecureloginhandler.h"
# include "msnchallengehandler.h"
# include <tqdatetime.h>
# include <tqregexp.h>
# include <tqdom.h>
# include <kdebug.h>
# include <tdeversion.h>
# include <tdelocale.h>
# include <kmdcodec.h>
# include <tdemessagebox.h>
# include <kstandarddirs.h>
# include <tdetempfile.h>
# include <krun.h>
# include <tdeio/job.h>
# include <tqfile.h>
# include <tdeconfig.h>
# include <knotification.h>
# include "kopeteuiglobal.h"
# include "kopeteglobal.h"
# include <ctime>
MSNNotifySocket : : MSNNotifySocket ( MSNAccount * account , const TQString & /*msnId*/ , const TQString & password )
: MSNSocket ( account )
{
m_newstatus = MSNProtocol : : protocol ( ) - > NLN ;
m_secureLoginHandler = 0L ;
m_challengeHandler = 0L ;
m_isHotmailAccount = false ;
m_ping = false ;
m_disconnectReason = Kopete : : Account : : Unknown ;
m_account = account ;
m_password = password ;
TQObject : : connect ( this , TQT_SIGNAL ( blockRead ( const TQByteArray & ) ) ,
this , TQT_SLOT ( slotReadMessage ( const TQByteArray & ) ) ) ;
m_keepaliveTimer = 0L ;
m_isLogged = false ;
}
MSNNotifySocket : : ~ MSNNotifySocket ( )
{
delete m_secureLoginHandler ;
delete m_challengeHandler ;
kdDebug ( 14140 ) < < k_funcinfo < < endl ;
}
void MSNNotifySocket : : doneConnect ( )
{
// kdDebug( 14140 ) << k_funcinfo << "Negotiating server protocol version" << endl;
sendCommand ( " VER " , " MSNP11 MSNP10 CVR0 " ) ;
}
void MSNNotifySocket : : disconnect ( )
{
m_isLogged = false ;
if ( m_disconnectReason = = Kopete : : Account : : Unknown )
m_disconnectReason = Kopete : : Account : : Manual ;
if ( onlineStatus ( ) = = Connected )
sendCommand ( " OUT " , TQString ( ) , false ) ;
if ( m_keepaliveTimer )
m_keepaliveTimer - > stop ( ) ;
// the socket is not connected yet, so I should force the signals
if ( onlineStatus ( ) = = Disconnected | | onlineStatus ( ) = = Connecting )
emit socketClosed ( ) ;
else
MSNSocket : : disconnect ( ) ;
}
void MSNNotifySocket : : handleError ( uint code , uint id )
{
kdDebug ( 14140 ) < < k_funcinfo < < endl ;
TQString handle ;
if ( m_tmpHandles . contains ( id ) )
handle = m_tmpHandles [ id ] ;
TQString msg ;
MSNSocket : : ErrorType type ;
// See http://www.hypothetic.org/docs/msn/basics.php for a
// description of all possible error codes.
// TODO: Add support for all of these!
switch ( code )
{
case 201 :
case 205 :
case 208 :
{
msg = i18n ( " <qt>The MSN user '%1' does not exist.<br>Please check the MSN ID.</qt> " ) . arg ( handle ) ;
type = MSNSocket : : ErrorServerError ;
break ;
}
case 207 :
case 218 :
case 540 :
{
msg = i18n ( " <qt>An internal error occurred in the MSN plugin.<br> "
" MSN Error: %1<br> "
" please send us a detailed bug report "
" at kopete-devel@kde.org containing the raw debug output on the "
" console (in gzipped format, as it is probably a lot of output.) " ) . arg ( code ) ;
type = MSNSocket : : ErrorServerError ;
break ;
}
case 209 :
{
if ( handle = = m_account - > accountId ( ) )
{
msg = i18n ( " Unable to change your display name. \n "
" Please ensure your display is not too long and does not contains censored words. " ) ;
type = MSNSocket : : ErrorServerError ;
}
/*else
{
TQString msg = i18n ( " You are trying to change the display name of a user who has not "
" confirmed his or her email address; \n "
" the contact was not renamed on the server. " ) ;
KMessageBox : : queuedMessageBox ( Kopete : : UI : : Global : : mainWidget ( ) , KMessageBox : : Error , msg , i18n ( " MSN Plugin " ) ) ;
} */
break ;
}
case 210 :
{
msg = i18n ( " Your contact list is full; you cannot add any new contacts. " ) ;
type = MSNSocket : : ErrorServerError ;
break ;
}
case 215 :
{
msg = i18n ( " <qt>The user '%1' already exists in this group on the MSN server;<br> "
" if Kopete does not show the user, please send us a detailed bug report "
" at kopete-devel@kde.org containing the raw debug output on the "
" console (in gzipped format, as it is probably a lot of output.)</qt> " ) . arg ( handle ) ;
type = MSNSocket : : ErrorInformation ;
break ;
}
case 216 :
{
//This might happen is you rename an user if he is not in the contactlist
//currently, we just iniore;
//TODO: try to don't rename user not in the list
//actualy, the bug is in MSNChatSession::slotUserJoined()
break ;
}
case 219 :
{
msg = i18n ( " The user '%1' seems to already be blocked or allowed on the server. " ) . arg ( handle ) ;
type = MSNSocket : : ErrorServerError ;
break ;
}
case 223 :
{
msg = i18n ( " You have reached the maximum number of groups: \n "
" MSN does not support more than 30 groups. " ) ;
type = MSNSocket : : ErrorServerError ;
break ;
}
case 224 :
case 225 :
case 230 :
{
msg = i18n ( " Kopete is trying to perform an operation on a group or a contact that does not exists on the server. \n "
" This might happen if the Kopete contact list and the MSN-server contact list are not correctly synchronized; if this is the case, you probably should send a bug report. " ) ;
type = MSNSocket : : ErrorServerError ;
break ;
}
case 229 :
{
msg = i18n ( " The group name is too long; it has not been changed on the MSN server. " ) ;
type = MSNSocket : : ErrorServerError ;
break ;
}
case 710 :
{
msg = i18n ( " You cannot open a Hotmail inbox because you do not have an MSN account with a valid "
" Hotmail or MSN mailbox. " ) ;
type = MSNSocket : : ErrorServerError ;
break ;
}
case 715 :
{
/*
//if(handlev==m_account->accountId())
TQString msg = i18n ( " Your email address has not been verified with the MSN server. \n "
" You should have received a mail with a link to confirm your email address. \n "
" Some functions will be restricted if you do not confirm your email address. " ) ;
KMessageBox : : queuedMessageBox ( Kopete : : UI : : Global : : mainWidget ( ) , KMessageBox : : Sorry , msg , i18n ( " MSN Plugin " ) ) ; //TODO don't show again
*/
break ;
}
case 800 :
{
//This happen when too much commends are sent to the server.
//the command will not be executed, too bad.
// ignore it for now, as we don't really know what command it was.
/* TQString msg = i18#n( "You are trying to change your status, or your display name too rapidly.\n"
" This might happen if you added yourself to your own contact list. " ) ;
KMessageBox : : queuedMessageBox ( Kopete : : UI : : Global : : mainWidget ( ) , KMessageBox : : Sorry , msg , i18n ( " MSN Plugin " ) ) ;
//FIXME: try to fix this problem*/
break ;
}
case 911 :
m_disconnectReason = Kopete : : Account : : BadPassword ;
disconnect ( ) ;
break ;
case 913 :
{
msg = i18n ( " You can not send messages when you are offline or when you are invisible. " ) ;
type = MSNSocket : : ErrorServerError ;
break ;
}
case 923 :
{
msg = i18n ( " You are trying to perform an action you are not allowed to perform in 'kid mode'. " ) ;
type = MSNSocket : : ErrorServerError ;
break ;
}
default :
MSNSocket : : handleError ( code , id ) ;
break ;
}
if ( ! msg . isEmpty ( ) )
emit errorMessage ( type , msg ) ;
}
void MSNNotifySocket : : parseCommand ( const TQString & cmd , uint id , const TQString & data )
{
//kdDebug(14140) << "MSNNotifySocket::parseCommand: Command: " << cmd << endl;
if ( cmd = = " VER " )
{
sendCommand ( " CVR " , " 0x0409 winnt 5.1 i386 MSNMSGR 7.0.0816 MSMSGS " + m_account - > accountId ( ) ) ;
/*
struct utsname utsBuf ;
uname ( & utsBuf ) ;
sendCommand ( " CVR " , i18n ( " MS Local code, see http://www.microsoft.com/globaldev/reference/oslocversion.mspx " , " 0x0409 " ) +
" " + escape ( utsBuf . sysname ) + " " + escape ( utsBuf . release ) + " " + escape ( utsBuf . machine ) + " Kopete " +
escape ( kapp - > aboutData ( ) - > version ( ) ) + " Kopete " + m_msnId ) ;
*/
}
else if ( cmd = = " CVR " ) //else if ( cmd == "INF" )
{
sendCommand ( " USR " , " TWN I " + m_account - > accountId ( ) ) ;
}
else if ( cmd = = " USR " ) //// here follow the auth processus
{
if ( data . section ( ' ' , 1 , 1 ) = = " S " )
{
m_secureLoginHandler = new MSNSecureLoginHandler ( m_account - > accountId ( ) , m_password , data . section ( ' ' , 2 , 2 ) ) ;
TQObject : : connect ( m_secureLoginHandler , TQT_SIGNAL ( loginFailed ( ) ) , this , TQT_SLOT ( sslLoginFailed ( ) ) ) ;
TQObject : : connect ( m_secureLoginHandler , TQT_SIGNAL ( loginBadPassword ( ) ) , this , TQT_SLOT ( sslLoginIncorrect ( ) ) ) ;
TQObject : : connect ( m_secureLoginHandler , TQT_SIGNAL ( loginSuccesful ( TQString ) ) , this , TQT_SLOT ( sslLoginSucceeded ( TQString ) ) ) ;
m_secureLoginHandler - > login ( ) ;
}
else
{
// Successful authentication.
m_disconnectReason = Kopete : : Account : : Unknown ;
// Synchronize with the server.
TQString lastSyncTime , lastChange ;
if ( m_account - > contacts ( ) . count ( ) > 1 )
{
// Retrieve the last synchronization timestamp, and last change timestamp.
lastSyncTime = m_account - > configGroup ( ) - > readEntry ( " lastsynctime " , " 0 " ) ;
lastChange = m_account - > configGroup ( ) - > readEntry ( " lastchange " , " 0 " ) ;
}
else
{
//the contactliust has maybe being removed, force to sync
//(the only contact is myself)
lastSyncTime = " 0 " ;
lastChange = " 0 " ;
}
sendCommand ( " SYN " , lastChange + " " + lastSyncTime ) ;
// Get client features.
if ( ! useHttpMethod ( ) ) {
sendCommand ( " GCF " , " Shields.xml " ) ;
// We are connected start to ping
slotSendKeepAlive ( ) ;
}
}
}
else if ( cmd = = " LST " )
{
// MSNP11 changed command. Now it's:
// LST N=passport@hotmail.com F=Display%20Name C=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 13 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// But can be
// LST N=passport@hotmail.com 10
TQString publicName , contactGuid , groups ;
uint lists ;
TQRegExp regex ( " N=([^ ]+) ( ? : F = ( [ ^ ] + ) ) ? ( ? : C = ( [ 0 - 9 a - fA - F ] { 8 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 12 } ) ) ? ( \ \ d + ) \ \ s ? ( ( ? : [ 0 - 9 a - fA - F ] { 8 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 12 } , ? ) * ) $ " );
regex . search ( data ) ;
// Capture passport email.
m_tmpLastHandle = regex . cap ( 1 ) ;
// Capture public name.
publicName = unescape ( regex . cap ( 2 ) ) ;
// Capture contact guid.
contactGuid = regex . cap ( 3 ) ;
// Capture list enum type.
lists = regex . cap ( 4 ) . toUInt ( ) ;
// Capture contact group(s) guid(s)
groups = regex . cap ( 5 ) ;
// kdDebug(14140) << k_funcinfo << " msnId: " << m_tmpLastHandle << " publicName: " << publicName << " contactGuid: " << contactGuid << " list: " << lists << " groupGuid: " << groups << endl;
// handle, publicName, Contact GUID, lists, Group GUID
emit contactList ( m_tmpLastHandle , publicName , contactGuid , lists , groups ) ;
}
else if ( cmd = = " GCF " )
{
m_configFile = data . section ( ' ' , 0 , 0 ) ;
readBlock ( data . section ( ' ' , 1 , 1 ) . toUInt ( ) ) ;
}
else if ( cmd = = " MSG " )
{
readBlock ( data . section ( ' ' , 2 , 2 ) . toUInt ( ) ) ;
}
else if ( cmd = = " ILN " | | cmd = = " NLN " )
{
// status handle publicName strangeNumber MSNOBJECT
MSNContact * c = static_cast < MSNContact * > ( m_account - > contacts ( ) [ data . section ( ' ' , 1 , 1 ) ] ) ;
if ( c & & c - > contactId ( ) ! = m_account - > accountId ( ) )
{
TQString publicName = unescape ( data . section ( ' ' , 2 , 2 ) ) ;
if ( ( publicName ! = c - > contactId ( ) | | c - > hasProperty ( Kopete : : Global : : Properties : : self ( ) - > nickName ( ) . key ( ) ) ) & &
publicName ! = c - > property ( Kopete : : Global : : Properties : : self ( ) - > nickName ( ) ) . value ( ) . toString ( ) )
changePublicName ( publicName , c - > contactId ( ) ) ;
TQString obj = unescape ( data . section ( ' ' , 4 , 4 ) ) ;
c - > setObject ( obj ) ;
c - > setOnlineStatus ( convertOnlineStatus ( data . section ( ' ' , 0 , 0 ) ) ) ;
c - > setClientFlags ( data . section ( ' ' , 3 , 3 ) . toUInt ( ) ) ;
}
}
else if ( cmd = = " UBX " )
{
m_tmpLastHandle = data . section ( ' ' , 0 , 0 ) ;
uint length = data . section ( ' ' , 1 , 1 ) . toUInt ( ) ;
if ( length > 0 ) {
readBlock ( length ) ;
}
}
else if ( cmd = = " UUX " )
{
// UUX is sended to acknowledge that the server has received and processed the personal Message.
// if the result is 0, set the myself() contact personalMessage.
if ( data . section ( ' ' , 0 , 0 ) = = TQString : : fromUtf8 ( " 0 " ) )
m_account - > myself ( ) - > setProperty ( MSNProtocol : : protocol ( ) - > propPersonalMessage , m_propertyPersonalMessage ) ;
}
else if ( cmd = = " FLN " )
{
MSNContact * c = static_cast < MSNContact * > ( m_account - > contacts ( ) [ data . section ( ' ' , 0 , 0 ) ] ) ;
if ( c & & c - > contactId ( ) ! = m_account - > accountId ( ) )
{
c - > setOnlineStatus ( MSNProtocol : : protocol ( ) - > FLN ) ;
c - > removeProperty ( MSNProtocol : : protocol ( ) - > propClient ) ;
}
}
else if ( cmd = = " XFR " )
{
TQString stype = data . section ( ' ' , 0 , 0 ) ;
if ( stype = = " SB " ) //switchboard connection (chat)
{
// Address, AuthInfo
emit startChat ( data . section ( ' ' , 1 , 1 ) , data . section ( ' ' , 3 , 3 ) ) ;
}
else if ( stype = = " NS " ) / / notifysocket ; Got our notification server
{ //we are connecting and we receive the initial NS, or the msn server encounter a problem, and we are switching to another switchboard
TQString host = data . section ( ' ' , 1 , 1 ) ;
TQString server = host . section ( ' : ' , 0 , 0 ) ;
uint port = host . section ( ' : ' , 1 , 1 ) . toUInt ( ) ;
setOnlineStatus ( Connected ) ;
emit receivedNotificationServer ( server , port ) ;
disconnect ( ) ;
}
}
else if ( cmd = = " RNG " )
{
// SessionID, Address, AuthInfo, handle, publicName
emit invitedToChat ( TQString : : number ( id ) , data . section ( ' ' , 0 , 0 ) , data . section ( ' ' , 2 , 2 ) ,
data . section ( ' ' , 3 , 3 ) , unescape ( data . section ( ' ' , 4 , 4 ) ) ) ;
}
else if ( cmd = = " ADC " )
{
TQString msnId , list , publicName , contactGuid , groupGuid ;
// Retrieve the list parameter (FL/AL/BL/RL)
list = data . section ( ' ' , 0 , 0 ) ;
// Examples of received data
// ADC TrID xL N=example@passport.com
// ADC TrID FL C=contactGuid groupdGuid
// ADC TrID RL N=example@passport.com F=friednly%20name
// ADC TrID FL N=ex@pas.com F=My%20Name C=contactGuid
// Thanks Gregg for that complex RegExp.
TQRegExp regex ( " (?:N=([^ ]+) ) ? ( ? : F = ( [ ^ ] + ) ) ? ( ? : C = ( [ 0 - 9 a - fA - F ] { 8 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 12 } ) ) ? \ \ s ? ( ( ? : [ 0 - 9 a - fA - F ] { 8 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 4 } \ \ - [ 0 - 9 a - fA - F ] { 12 } , ? ) * ) $ " );
regex . search ( data . section ( ' ' , 1 ) ) ;
// Capture passport email.
msnId = regex . cap ( 1 ) ;
// Capture public name.
publicName = unescape ( regex . cap ( 2 ) ) ;
// Capture contact guid.
contactGuid = regex . cap ( 3 ) ;
// Capture contact group(s) guid(s)
groupGuid = regex . cap ( 4 ) ;
// kdDebug(14140) << k_funcinfo << list << " msnId: " << msnId << " publicName: " << publicName << " contactGuid: " << contactGuid << " groupGuid: " << groupGuid << endl;
// handle, list, publicName, contactGuid, groupGuid
emit contactAdded ( msnId , list , publicName , contactGuid , groupGuid ) ;
}
else if ( cmd = = " REM " ) // someone is removed from a list
{
TQString handle , list , contactGuid , groupGuid ;
list = data . section ( ' ' , 0 , 0 ) ;
if ( list = = " FL " )
{
// Removing a contact
if ( data . contains ( ' ' ) < 2 )
{
contactGuid = data . section ( ' ' , 1 , 1 ) ;
}
// Removing a contact from a group
else if ( data . contains ( ' ' ) < 3 )
{
contactGuid = data . section ( ' ' , 1 , 1 ) ;
groupGuid = data . section ( ' ' , 2 , 2 ) ;
}
}
else
{
handle = data . section ( ' ' , 1 , 1 ) ;
}
// handle, list, contactGuid, groupGuid
emit contactRemoved ( handle , list , contactGuid , groupGuid ) ;
}
else if ( cmd = = " OUT " )
{
if ( data . section ( ' ' , 0 , 0 ) = = " OTH " )
{
m_disconnectReason = Kopete : : Account : : OtherClient ;
}
disconnect ( ) ;
}
else if ( cmd = = " CHG " )
{
TQString status = data . section ( ' ' , 0 , 0 ) ;
setOnlineStatus ( Connected ) ;
emit statusChanged ( convertOnlineStatus ( status ) ) ;
}
else if ( cmd = = " SBP " )
{
TQString contactGuid , type , publicName ;
contactGuid = data . section ( ' ' , 0 , 0 ) ;
type = data . section ( ' ' , 1 , 1 ) ;
if ( type = = " MFN " )
{
publicName = unescape ( data . section ( ' ' , 2 , 2 ) ) ;
MSNContact * c = m_account - > findContactByGuid ( contactGuid ) ;
if ( c ! = 0L )
{
c - > setProperty ( Kopete : : Global : : Properties : : self ( ) - > nickName ( ) , publicName ) ;
}
}
}
else if ( cmd = = " LSG " )
{
// New Format: LSG Friends xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// groupDisplayName, groupGuid
emit groupListed ( unescape ( data . section ( ' ' , 0 , 0 ) ) , data . section ( ' ' , 1 , 1 ) ) ;
}
else if ( cmd = = " ADG " )
{
// groupName, groupGuid
emit groupAdded ( unescape ( data . section ( ' ' , 0 , 0 ) ) ,
data . section ( ' ' , 1 , 1 ) ) ;
}
else if ( cmd = = " REG " )
{
// groupGuid, groupName
emit groupRenamed ( data . section ( ' ' , 0 , 0 ) , unescape ( data . section ( ' ' , 1 , 1 ) ) ) ;
}
else if ( cmd = = " RMG " )
{
// groupGuid
emit groupRemoved ( data . section ( ' ' , 1 , 1 ) ) ;
}
else if ( cmd = = " CHL " )
{
m_challengeHandler = new MSNChallengeHandler ( " CFHUR$52U_{VIX5T " , " PROD0101{0RM?UBW " ) ;
// Compute the challenge response hash, and send the response.
TQString chlResponse = m_challengeHandler - > computeHash ( data . section ( ' ' , 0 , 0 ) ) ;
sendCommand ( " QRY " , m_challengeHandler - > productId ( ) , true , chlResponse . utf8 ( ) ) ;
// Dispose of the challenge handler.
m_challengeHandler - > deleteLater ( ) ;
m_challengeHandler = 0L ;
}
else if ( cmd = = " SYN " )
{
// Retrieve the last synchronization timestamp known to the server.
TQString lastSyncTime = data . section ( ' ' , 1 , 1 ) ;
TQString lastChange = data . section ( ' ' , 0 , 0 ) ;
if ( lastSyncTime ! = m_account - > configGroup ( ) - > readEntry ( " lastsynctime " ) | |
lastChange ! = m_account - > configGroup ( ) - > readEntry ( " lastchange " ) )
{
// If the server timestamp and the local timestamp are different,
// prepare to receive the contact list.
emit newContactList ( ) ; // remove all contacts datas, msn sends a new contact list
m_account - > configGroup ( ) - > writeEntry ( " lastsynctime " , lastSyncTime ) ;
m_account - > configGroup ( ) - > writeEntry ( " lastchange " , lastChange ) ;
} else
kdDebug ( 14140 ) < < k_funcinfo < < " Contact list up-to-date. " < < endl ;
// set the status
setStatus ( m_newstatus ) ;
}
else if ( cmd = = " BPR " )
{
MSNContact * c = static_cast < MSNContact * > ( m_account - > contacts ( ) [ m_tmpLastHandle ] ) ;
if ( c )
c - > setInfo ( data . section ( ' ' , 0 , 0 ) , unescape ( data . section ( ' ' , 1 , 1 ) ) ) ;
}
else if ( cmd = = " PRP " )
{
MSNContact * c = static_cast < MSNContact * > ( m_account - > myself ( ) ) ;
if ( c )
{
TQString type = data . section ( ' ' , 0 , 0 ) ;
TQString prpData = unescape ( data . section ( ' ' , 1 , 1 ) ) ; //SECURITY????????
c - > setInfo ( type , prpData ) ;
m_account - > configGroup ( ) - > writeEntry ( type , prpData ) ;
}
}
else if ( cmd = = " BLP " )
{
if ( id > 0 ) //FROM BLP
{
m_account - > configGroup ( ) - > writeEntry ( " serial " , data . section ( ' ' , 0 , 0 ) ) ;
m_account - > configGroup ( ) - > writeEntry ( " BLP " , data . section ( ' ' , 1 , 1 ) ) ;
}
else //FROM SYN
m_account - > configGroup ( ) - > writeEntry ( " BLP " , data . section ( ' ' , 0 , 0 ) ) ;
}
else if ( cmd = = " QRY " )
{
// Do nothing
}
else if ( cmd = = " QNG " )
{
//this is a reply from a ping
m_ping = false ;
// id is the timeout in fact, and we remove 5% of it
if ( m_keepaliveTimer )
m_keepaliveTimer - > start ( id * 950 , true ) ;
kdDebug ( 14140 ) < < k_funcinfo < < " timerTimeout= " < < id < < " sec " < < endl ;
}
else if ( cmd = = " URL " )
{
// URL 6 /cgi-bin/HoTMaiL https://loginnet.passport.com/ppsecure/md5auth.srf?lc=1033 2
//example of reply: URL 10 /cgi-bin/HoTMaiL https://msnialogin.passport.com/ppsecure/md5auth.srf?lc=1036 3
TQString from_action_url = data . section ( ' ' , 1 , 1 ) ;
TQString rru = data . section ( ' ' , 0 , 0 ) ;
TQString id = data . section ( ' ' , 2 , 2 ) ;
//write the tmp file
TQString UserID = m_account - > accountId ( ) ;
time_t actualTime ;
time ( & actualTime ) ;
TQString sl = TQString : : number ( ( unsigned long ) actualTime - m_loginTime . toULong ( ) ) ;
TQString md5this ( m_MSPAuth + sl + m_password ) ;
KMD5 md5 ( md5this . utf8 ( ) ) ;
TQString hotmailRequest = " <html> \n "
" <head> \n "
" <noscript> \n "
" <meta http-equiv=Refresh content= \" 0; url=http://www.hotmail.com \" > \n "
" </noscript> \n "
" </head> \n "
" <body onload= \" document.pform.submit(); \" > \n "
" <form name= \" pform \" action= \" " + from_action_url + " \" method= \" POST \" > \n "
" <input type= \" hidden \" name= \" mode \" value= \" ttl \" > \n "
" <input type= \" hidden \" name= \" login \" value= \" " + UserID . left ( UserID . find ( ' @ ' ) ) + " \" > \n "
" <input type= \" hidden \" name= \" username \" value= \" " + UserID + " \" > \n "
" <input type= \" hidden \" name= \" sid \" value= \" " + m_sid + " \" > \n "
" <input type= \" hidden \" name= \" kv \" value= \" " + m_kv + " \" > \n "
" <input type= \" hidden \" name= \" id \" value= \" " + id + " \" > \n "
" <input type= \" hidden \" name= \" sl \" value= \" " + sl + " \" > \n "
" <input type= \" hidden \" name= \" rru \" value= \" " + rru + " \" > \n "
" <input type= \" hidden \" name= \" auth \" value= \" " + m_MSPAuth + " \" > \n "
" <input type= \" hidden \" name= \" creds \" value= \" " + TQString : : fromLatin1 ( md5 . hexDigest ( ) ) + " \" > \n "
" <input type= \" hidden \" name= \" svc \" value= \" mail \" > \n "
" <input type= \" hidden \" name= \" js \" value= \" yes \" > \n "
" </form></body> \n </html> \n " ;
KTempFile tmpMailFile ( locateLocal ( " tmp " , " kopetehotmail- " ) , " .html " ) ;
* tmpMailFile . textStream ( ) < < hotmailRequest ;
tmpMailFile . file ( ) - > flush ( ) ;
KRun : : runURL ( KURL : : fromPathOrURL ( tmpMailFile . name ( ) ) , " text/html " , true ) ;
}
else if ( cmd = = " NOT " )
{
kdDebug ( 14140 ) < < k_funcinfo < < " Received NOT command, issueing read block for ' " < < id < < " more bytes " < < endl ;
readBlock ( id ) ;
}
else
{
// Let the base class handle the rest
//MSNSocket::parseCommand( cmd, id, data );
kdDebug ( 14140 ) < < k_funcinfo < < " Unimplemented command ' " < < cmd < < " " < < id < < " " < < data < < " ' from server! " < < endl ;
}
}
void MSNNotifySocket : : sslLoginFailed ( )
{
m_disconnectReason = Kopete : : Account : : InvalidHost ;
disconnect ( ) ;
}
void MSNNotifySocket : : sslLoginIncorrect ( )
{
m_disconnectReason = Kopete : : Account : : BadPassword ;
disconnect ( ) ;
}
void MSNNotifySocket : : sslLoginSucceeded ( TQString ticket )
{
sendCommand ( " USR " , " TWN S " + ticket ) ;
m_secureLoginHandler - > deleteLater ( ) ;
m_secureLoginHandler = 0L ;
}
void MSNNotifySocket : : slotMSNAlertUnwanted ( )
{
// user not interested .. clean up the list of actions
m_msnAlertURLs . clear ( ) ;
}
void MSNNotifySocket : : slotMSNAlertLink ( unsigned int action )
{
// index into our action list and pull out the URL that was clicked ..
KURL tempURLForLaunch ( m_msnAlertURLs [ action - 1 ] ) ;
KRun * urlToRun = new KRun ( tempURLForLaunch ) ;
}
void MSNNotifySocket : : slotOpenInbox ( )
{
sendCommand ( " URL " , " INBOX " ) ;
}
void MSNNotifySocket : : sendMail ( const TQString & email )
{
sendCommand ( " URL " , TQString ( " COMPOSE " + email ) . utf8 ( ) ) ;
}
bool MSNNotifySocket : : setUseHttpMethod ( bool useHttp )
{
bool ret = MSNSocket : : setUseHttpMethod ( useHttp ) ;
if ( useHttpMethod ( ) ) {
if ( m_keepaliveTimer ) {
delete m_keepaliveTimer ;
m_keepaliveTimer = 0L ;
}
}
else {
if ( ! m_keepaliveTimer ) {
m_keepaliveTimer = new TQTimer ( this , " m_keepaliveTimer " ) ;
TQObject : : connect ( m_keepaliveTimer , TQT_SIGNAL ( timeout ( ) ) , TQT_SLOT ( slotSendKeepAlive ( ) ) ) ;
}
}
return ret ;
}
void MSNNotifySocket : : slotReadMessage ( const TQByteArray & bytes )
{
TQString msg = TQString : : fromUtf8 ( bytes , bytes . size ( ) ) ;
if ( msg . contains ( " text/x-msmsgsinitialmdatanotification " ) )
{
//Mail-Data: <MD><E><I>301</I><IU>1</IU><O>4</O><OU>2</OU></E><Q><TQTM>409600</TQTM><TQNM>204800</TQNM></Q></MD>
// MD - Mail Data
// E - email
// I - initial mail
// IU - initial unread
// O - other mail
// OU - other unread.
TQRegExp regex ( " <MD><E><I>( \\ d+) ? < / I > ( ? : < IU > ( \ \ d + ) ? < / IU > ) < O > ( \ \ d + ) ? < / O > < OU > ( \ \ d + ) ? < / OU > < / E > < Q > . * < / Q > < / MD > " ) ;
regex . search ( msg ) ;
bool unread ;
// Retrieve the number of unread email messages.
mailCount = regex . cap ( 2 ) . toUInt ( & unread ) ;
if ( unread & & mailCount > 0 )
{
// If there are new email message available, raise the unread email event.
TQObject : : connect ( KNotification : : event ( " msn_mail " , i18n ( " You have one unread message in your MSN inbox. " ,
" You have %n unread messages in your MSN inbox. " , mailCount ) , 0 , 0 , i18n ( " Open Inbox... " ) ) ,
TQT_SIGNAL ( activated ( unsigned int ) ) , this , TQT_SLOT ( slotOpenInbox ( ) ) ) ;
}
}
else if ( msg . contains ( " text/x-msmsgsactivemailnotification " ) )
{
//this sends the server if mails are deleted
TQString m = msg . right ( msg . length ( ) - msg . find ( " Message-Delta: " ) ) ;
m = m . left ( msg . find ( " \r \n " ) ) ;
mailCount = mailCount - m . right ( m . length ( ) - m . find ( " " ) - 1 ) . toUInt ( ) ;
}
else if ( msg . contains ( " text/x-msmsgsemailnotification " ) )
{
//this sends the server if a new mail has arrived
TQRegExp rx ( " From-Addr: ([A-Za-z0-9@._ \\ -]*) " ) ;
rx . search ( msg ) ;
TQString m = rx . cap ( 1 ) ;
mailCount + + ;
//TODO: it is also possible to get the subject (but warning about the encoding)
TQObject : : connect ( KNotification : : event ( " msn_mail " , i18n ( " You have one new email from %1 in your MSN inbox. " ) . arg ( m ) ,
0 , 0 , i18n ( " Open Inbox... " ) ) ,
TQT_SIGNAL ( activated ( unsigned int ) ) , this , TQT_SLOT ( slotOpenInbox ( ) ) ) ;
}
else if ( msg . contains ( " text/x-msmsgsprofile " ) )
{
//Hotmail profile
if ( msg . contains ( " MSPAuth: " ) )
{
TQRegExp rx ( " MSPAuth: ([A-Za-z0-9$!*]*) " ) ;
rx . search ( msg ) ;
m_MSPAuth = rx . cap ( 1 ) ;
}
if ( msg . contains ( " sid: " ) )
{
TQRegExp rx ( " sid: ([0-9]*) " ) ;
rx . search ( msg ) ;
m_sid = rx . cap ( 1 ) ;
}
if ( msg . contains ( " kv: " ) )
{
TQRegExp rx ( " kv: ([0-9]*) " ) ;
rx . search ( msg ) ;
m_kv = rx . cap ( 1 ) ;
}
if ( msg . contains ( " LoginTime: " ) )
{
TQRegExp rx ( " LoginTime: ([0-9]*) " ) ;
rx . search ( msg ) ;
m_loginTime = rx . cap ( 1 ) ;
}
else //IN MSNP9 there are no logintime it seems, so set it manualy
{
time_t actualTime ;
time ( & actualTime ) ;
m_loginTime = TQString : : number ( ( unsigned long ) actualTime ) ;
}
if ( msg . contains ( " EmailEnabled: " ) )
{
TQRegExp rx ( " EmailEnabled: ([0-9]*) " ) ;
rx . search ( msg ) ;
m_isHotmailAccount = ( rx . cap ( 1 ) . toUInt ( ) = = 1 ) ;
emit hotmailSeted ( m_isHotmailAccount ) ;
}
if ( msg . contains ( " ClientIP: " ) )
{
TQRegExp rx ( " ClientIP: ([0-9.]*) " ) ;
rx . search ( msg ) ;
m_localIP = rx . cap ( 1 ) ;
}
// We are logged when we receive the initial profile from Hotmail.
m_isLogged = true ;
}
else if ( msg . contains ( " NOTIFICATION " ) )
{
// MSN alert (i.e. NOTIFICATION) [for docs see http://www.hypothetic.org/docs/msn/client/notification.php]
// format of msg is as follows:
//
// <NOTIFICATION ver="2" id="1342902633" siteid="199999999" siteurl="http://alerts.msn.com">
// <TO pid="0x0006BFFD:0x8582C0FB" name="example@passport.com"/>
// <MSG pri="1" id="1342902633">
// <SUBSCR url="http://g.msn.com/3ALMSNTRACKING/199999999ToastChange?http://alerts.msn.com/Alerts/MyAlerts.aspx?strela=1"/>
// <ACTION url="http://g.msn.com/3ALMSNTRACKING/199999999ToastAction?http://alerts.msn.com/Alerts/MyAlerts.aspx?strela=1"/>
// <BODY lang="3076" icon="">
// <TEXT>utf8-encoded text</TEXT>
// </BODY>
// </MSG>
// </NOTIFICATION>
// MSN sends out badly formed XML .. fix it for them (thanks MS!)
TQString notificationDOMAsString ( msg ) ;
TQRegExp rx ( " &(?!amp;) " ) ; // match ampersands but not &
notificationDOMAsString . replace ( rx , " & " ) ;
TQDomDocument alertDOM ;
alertDOM . setContent ( notificationDOMAsString ) ;
TQDomNodeList msgElements = alertDOM . elementsByTagName ( " MSG " ) ;
for ( uint i = 0 ; i < msgElements . count ( ) ; i + + )
{
TQString subscString ;
TQString actionString ;
TQString textString ;
TQDomNode msgDOM = msgElements . item ( i ) ;
TQDomNodeList msgChildren = msgDOM . childNodes ( ) ;
for ( uint i = 0 ; i < msgChildren . length ( ) ; i + + ) {
TQDomNode child = msgChildren . item ( i ) ;
TQDomElement element = child . toElement ( ) ;
if ( element . tagName ( ) = = " SUBSCR " )
{
TQDomAttr subscElementURLAttribute ;
if ( element . hasAttribute ( " url " ) )
{
subscElementURLAttribute = element . attributeNode ( " url " ) ;
subscString = subscElementURLAttribute . value ( ) ;
}
}
else if ( element . tagName ( ) = = " ACTION " )
{
// process ACTION node to pull out URL the alert is tied to
TQDomAttr actionElementURLAttribute ;
if ( element . hasAttribute ( " url " ) )
{
actionElementURLAttribute = element . attributeNode ( " url " ) ;
actionString = actionElementURLAttribute . value ( ) ;
}
}
else if ( element . tagName ( ) = = " BODY " )
{
// process BODY node to get the text of the alert
TQDomNodeList textElements = element . elementsByTagName ( " TEXT " ) ;
if ( textElements . count ( ) > = 1 )
{
TQDomElement textElement = textElements . item ( 0 ) . toElement ( ) ;
textString = textElement . text ( ) ;
}
}
}
// kdDebug( 14140 ) << "subscString " << subscString << " actionString " << actionString << " textString " << textString << endl;
// build an internal list of actions ... we'll need to index into this list when we receive an event
TQStringList actions ;
actions . append ( i18n ( " More Information " ) ) ;
m_msnAlertURLs . append ( actionString ) ;
actions . append ( i18n ( " Manage Subscription " ) ) ;
m_msnAlertURLs . append ( subscString ) ;
// Don't do any MSN alerts notification for new blog updates
if ( subscString ! = TQString : : fromLatin1 ( " s.htm " ) & & actionString ! = TQString : : fromLatin1 ( " a.htm " ) )
{
KNotification * notification = KNotification : : event ( " msn_alert " , textString , 0L , 0L , actions ) ;
TQObject : : connect ( notification , TQT_SIGNAL ( activated ( unsigned int ) ) , this , TQT_SLOT ( slotMSNAlertLink ( unsigned int ) ) ) ;
TQObject : : connect ( notification , TQT_SIGNAL ( closed ( ) ) , this , TQT_SLOT ( slotMSNAlertUnwanted ( ) ) ) ;
}
} // end for each MSG tag
}
if ( ! m_configFile . isNull ( ) )
{
// TODO Get client features.
}
if ( ! m_tmpLastHandle . isNull ( ) )
{
TQString personalMessage , currentMedia ;
TQDomDocument psm ;
if ( psm . setContent ( msg ) )
{
// Get the first child of the xml "document";
TQDomElement psmElement = psm . documentElement ( ) . firstChild ( ) . toElement ( ) ;
while ( ! psmElement . isNull ( ) )
{
if ( psmElement . tagName ( ) = = TQString : : fromUtf8 ( " PSM " ) )
{
personalMessage = psmElement . text ( ) ;
kdDebug ( 14140 ) < < k_funcinfo < < " Personnal Message received: " < < personalMessage < < endl ;
}
else if ( psmElement . tagName ( ) = = TQString : : fromUtf8 ( " CurrentMedia " ) )
{
if ( ! psmElement . text ( ) . isEmpty ( ) )
{
kdDebug ( 14140 ) < < k_funcinfo < < " XML CurrentMedia: " < < psmElement . text ( ) < < endl ;
currentMedia = processCurrentMedia ( psmElement . text ( ) ) ;
}
}
psmElement = psmElement . nextSibling ( ) . toElement ( ) ;
}
MSNContact * contact = static_cast < MSNContact * > ( m_account - > contacts ( ) [ m_tmpLastHandle ] ) ;
if ( contact )
{
contact - > setProperty ( MSNProtocol : : protocol ( ) - > propPersonalMessage , currentMedia . isEmpty ( ) ? personalMessage : currentMedia ) ;
}
}
m_tmpLastHandle = TQString ( ) ;
}
}
TQString MSNNotifySocket : : processCurrentMedia ( const TQString & mediaXmlElement )
{
/*
The value of the CurrentMedia tag you can think of like an array
seperated by " \0 " characters ( literal backslash followed by zero , not NULL ) .
The elements of this " array " are as follows :
* Application - This is the app you are using . Usually empty
* Type - This is the type of PSM , either “ Music ” , “ Games ” or “ Office ”
* Enabled - This is a boolean value ( 0 / 1 ) to enable / disable
* Format - A formatter string ala . Net ; For example , “ { 0 } - { 1 } ”
* First line - The first line ( Matches { 0 } in the Format )
* Second line - The second line ( Matches { 1 } in the Format )
* Third line - The third line ( Matches { 2 } in the Format )
There is probably no limit to the number of lines unless you go over the maximum length of the tag .
Example of currentMedia xml tag :
< CurrentMedia > \ 0 Music \ 01 \ 0 { 0 } - { 1 } \ 0 Song Title \ 0 Song Artist \ 0 Song Album \ 0 \ 0 < / CurrentMedia >
< CurrentMedia > \ 0 Games \ 01 \ 0 Playing { 0 } \ 0 Game Name \ 0 < / CurrentMedia >
< CurrentMedia > \ 0 Office \ 01 \ 0 Office Message \ 0 Office App Name \ 0 < / CurrentMedia >
From http : //msnpiki.msnfanatic.com/index.php/MSNP11:Changes
*/
TQString application , type , format , currentMedia ;
bool enabled = false , test ;
// \0 is textual, it's the "array" separator.
TQStringList argumentLists = TQStringList : : split ( TQString : : fromUtf8 ( " \\ 0 " ) , mediaXmlElement , true ) ;
// Retrive the "stable" array elements.
application = argumentLists [ 0 ] ;
type = argumentLists [ 1 ] ;
enabled = argumentLists [ 2 ] . toInt ( & test ) ;
format = argumentLists [ 3 ] ;
// Get the formatter strings
TQStringList formatterStrings ;
TQStringList : : ConstIterator it ;
for ( it = argumentLists . at ( 4 ) ; it ! = argumentLists . end ( ) ; + + it )
{
formatterStrings . append ( * it ) ;
}
// Replace the formatter in the format string.
currentMedia = format ;
for ( uint i = 0 ; i < formatterStrings . size ( ) ; i + + )
{
currentMedia = currentMedia . replace ( TQString ( " {%1} " ) . arg ( i ) , formatterStrings [ i ] ) ;
}
if ( type = = TQString : : fromUtf8 ( " Music " ) )
{
// the "♫" is encoded in utf8 (and should be in utf8)
currentMedia = i18n ( " Now Listening: ♫ %1 ♫ " ) . arg ( currentMedia ) ;
}
kdDebug ( 1414 ) < < " Current Media received: " < < currentMedia < < endl ;
return currentMedia ;
}
void MSNNotifySocket : : addGroup ( const TQString & groupName )
{
// escape spaces
sendCommand ( " ADG " , escape ( groupName ) ) ;
}
void MSNNotifySocket : : renameGroup ( const TQString & groupName , const TQString & groupGuid )
{
// escape spaces
sendCommand ( " REG " , groupGuid + " " + escape ( groupName ) ) ;
}
void MSNNotifySocket : : removeGroup ( const TQString & groupGuid )
{
sendCommand ( " RMG " , groupGuid ) ;
}
void MSNNotifySocket : : addContact ( const TQString & handle , int list , const TQString & publicName , const TQString & contactGuid , const TQString & groupGuid )
{
TQString args ;
switch ( list )
{
case MSNProtocol : : FL :
{
// Adding the contact to a group
if ( ! contactGuid . isEmpty ( ) )
{
args = TQString ( " FL C=%1 %2 " ) . arg ( contactGuid ) . arg ( groupGuid ) ;
kdDebug ( 14140 ) < < k_funcinfo < < " In adding contact to a group " < < endl ;
}
// Adding a new contact
else
{
args = TQString ( " FL N=%1 F=%2 " ) . arg ( handle ) . arg ( escape ( publicName ) ) ;
kdDebug ( 14140 ) < < k_funcinfo < < " In adding contact to a new contact " < < endl ;
}
break ;
}
case MSNProtocol : : AL :
args = TQString ( " AL N=%1 " ) . arg ( handle ) ;
break ;
case MSNProtocol : : BL :
args = TQString ( " BL N=%1 " ) . arg ( handle ) ;
break ;
case MSNProtocol : : RL :
args = TQString ( " RL N=%1 " ) . arg ( handle ) ;
break ;
default :
kdDebug ( 14140 ) < < k_funcinfo < < " WARNING! Unknown list " < < list < < " ! " < < endl ;
return ;
}
unsigned int id = sendCommand ( " ADC " , args ) ;
m_tmpHandles [ id ] = handle ;
}
void MSNNotifySocket : : removeContact ( const TQString & handle , int list , const TQString & contactGuid , const TQString & groupGuid )
{
TQString args ;
switch ( list )
{
case MSNProtocol : : FL :
args = " FL " + contactGuid ;
// Removing a contact from a group
if ( ! groupGuid . isEmpty ( ) )
args + = " " + groupGuid ;
break ;
case MSNProtocol : : AL :
args = " AL " + handle ;
break ;
case MSNProtocol : : BL :
args = " BL " + handle ;
break ;
case MSNProtocol : : PL :
args = " PL " + handle ;
break ;
default :
kdDebug ( 14140 ) < < k_funcinfo < < " WARNING! Unknown list " < < list < < " ! " < < endl ;
return ;
}
unsigned int id = sendCommand ( " REM " , args ) ;
m_tmpHandles [ id ] = handle ;
}
void MSNNotifySocket : : setStatus ( const Kopete : : OnlineStatus & status )
{
// kdDebug( 14140 ) << k_funcinfo << statusToString( status ) << endl;
if ( onlineStatus ( ) = = Disconnected )
m_newstatus = status ;
else
sendCommand ( " CHG " , statusToString ( status ) + " " + m_account - > myselfClientId ( ) + " " + escape ( m_account - > pictureObject ( ) ) ) ;
}
void MSNNotifySocket : : changePublicName ( const TQString & publicName , const TQString & handle )
{
TQString tempPublicName = publicName ;
//The maximum length is 387. but with utf8 or encodage, each character may be triple
// 387/3 = 129 so we make sure the length is not longer than 129 char, even if
// it's possible to have longer nicks.
if ( escape ( publicName ) . length ( ) > 129 )
{
tempPublicName = publicName . left ( 129 ) ;
}
if ( handle . isNull ( ) )
{
unsigned int id = sendCommand ( " PRP " , " MFN " + escape ( tempPublicName ) ) ;
m_tmpHandles [ id ] = m_account - > accountId ( ) ;
}
else
{
MSNContact * currentContact = static_cast < MSNContact * > ( m_account - > contacts ( ) [ handle ] ) ;
if ( currentContact & & ! currentContact - > guid ( ) . isEmpty ( ) )
{
// FIXME if there is not guid server disconnects.
unsigned int id = sendCommand ( " SBP " , currentContact - > guid ( ) + " MFN " + escape ( tempPublicName ) ) ;
m_tmpHandles [ id ] = handle ;
}
}
}
void MSNNotifySocket : : changePersonalMessage ( MSNProtocol : : PersonalMessageType type , const TQString & personalMessage )
{
TQString tempPersonalMessage ;
TQString xmlCurrentMedia ;
// Only espace and cut the personalMessage is the type is normal.
if ( type = = MSNProtocol : : PersonalMessageNormal )
{
tempPersonalMessage = personalMessage ;
//Magic number : 129 characters
if ( escape ( personalMessage ) . length ( ) > 129 )
{
// We cut. for now.
tempPersonalMessage = personalMessage . left ( 129 ) ;
}
}
TQDomDocument xmlMessage ;
xmlMessage . appendChild ( xmlMessage . createElement ( " Data " ) ) ;
TQDomElement psm = xmlMessage . createElement ( " PSM " ) ;
psm . appendChild ( xmlMessage . createTextNode ( tempPersonalMessage ) ) ;
xmlMessage . documentElement ( ) . appendChild ( psm ) ;
TQDomElement currentMedia = xmlMessage . createElement ( " CurrentMedia " ) ;
/* Example of currentMedia xml tag:
< CurrentMedia > \ 0 Music \ 01 \ 0 { 0 } - { 1 } \ 0 Song Title \ 0 Song Artist \ 0 Song Album \ 0 \ 0 < / CurrentMedia >
< CurrentMedia > \ 0 Games \ 01 \ 0 Playing { 0 } \ 0 Game Name \ 0 < / CurrentMedia >
< CurrentMedia > \ 0 Office \ 01 \ 0 Office Message \ 0 Office App Name \ 0 < / CurrentMedia >
*/
switch ( type )
{
case MSNProtocol : : PersonalMessageMusic :
{
xmlCurrentMedia = " \\ 0Music \\ 01 \\ 0 " ;
TQStringList mediaList = TQStringList : : split ( " ; " , personalMessage ) ;
TQString formatterArguments ;
if ( ! mediaList [ 0 ] . isEmpty ( ) ) // Current Track
{
xmlCurrentMedia + = " {0} " ;
formatterArguments + = TQString ( " %1 \\ 0 " ) . arg ( mediaList [ 0 ] ) ;
}
if ( ! mediaList [ 1 ] . isEmpty ( ) ) // Current Artist
{
xmlCurrentMedia + = " - {1} " ;
formatterArguments + = TQString ( " %1 \\ 0 " ) . arg ( mediaList [ 1 ] ) ;
}
if ( ! mediaList [ 2 ] . isEmpty ( ) ) // Current Album
{
xmlCurrentMedia + = " ({2}) " ;
formatterArguments + = TQString ( " %1 \\ 0 " ) . arg ( mediaList [ 2 ] ) ;
}
xmlCurrentMedia + = " \\ 0 " + formatterArguments + " \\ 0 " ;
break ;
}
default :
break ;
}
currentMedia . appendChild ( xmlMessage . createTextNode ( xmlCurrentMedia ) ) ;
// Set the status message for myself, check if currentMedia is empty, for either using the normal or Music personal
m_propertyPersonalMessage = xmlCurrentMedia . isEmpty ( ) ? tempPersonalMessage : processCurrentMedia ( currentMedia . text ( ) ) ;
xmlMessage . documentElement ( ) . appendChild ( currentMedia ) ;
unsigned int id = sendCommand ( " UUX " , " " , true , xmlMessage . toString ( ) . utf8 ( ) , false ) ;
m_tmpHandles [ id ] = m_account - > accountId ( ) ;
}
void MSNNotifySocket : : changePhoneNumber ( const TQString & key , const TQString & data )
{
sendCommand ( " PRP " , key + " " + escape ( data ) ) ;
}
void MSNNotifySocket : : createChatSession ( )
{
sendCommand ( " XFR " , " SB " ) ;
}
TQString MSNNotifySocket : : statusToString ( const Kopete : : OnlineStatus & status ) const
{
if ( status = = MSNProtocol : : protocol ( ) - > NLN )
return " NLN " ;
else if ( status = = MSNProtocol : : protocol ( ) - > BSY )
return " BSY " ;
else if ( status = = MSNProtocol : : protocol ( ) - > BRB )
return " BRB " ;
else if ( status = = MSNProtocol : : protocol ( ) - > AWY )
return " AWY " ;
else if ( status = = MSNProtocol : : protocol ( ) - > PHN )
return " PHN " ;
else if ( status = = MSNProtocol : : protocol ( ) - > LUN )
return " LUN " ;
else if ( status = = MSNProtocol : : protocol ( ) - > FLN )
return " FLN " ;
else if ( status = = MSNProtocol : : protocol ( ) - > HDN )
return " HDN " ;
else if ( status = = MSNProtocol : : protocol ( ) - > IDL )
return " IDL " ;
else
{
kdWarning ( 14140 ) < < k_funcinfo < < " Unknown status " < < status . internalStatus ( ) < < " ! " < < endl ;
return " UNK " ;
}
}
void MSNNotifySocket : : slotSendKeepAlive ( )
{
//we did not received the previous TQNG
if ( m_ping )
{
m_disconnectReason = Kopete : : Account : : ConnectionReset ;
disconnect ( ) ;
/*KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget(), KMessageBox::Information,
i18n ( " The connection with the MSN network has been lost. " ) , i18n ( " MSN Plugin " ) ) ; */
return ;
}
else
{
// Send a dummy command to fake activity. This makes sure MSN doesn't
// disconnect you when the notify socket is idle.
sendCommand ( " PNG " , TQString ( ) , false ) ;
m_ping = true ;
}
//at least 90 second has been ellapsed since the last messages
// we shouldn't receive error from theses command anymore
m_tmpHandles . clear ( ) ;
}
Kopete : : OnlineStatus MSNNotifySocket : : convertOnlineStatus ( const TQString & status )
{
if ( status = = " NLN " )
return MSNProtocol : : protocol ( ) - > NLN ;
else if ( status = = " FLN " )
return MSNProtocol : : protocol ( ) - > FLN ;
else if ( status = = " HDN " )
return MSNProtocol : : protocol ( ) - > HDN ;
else if ( status = = " PHN " )
return MSNProtocol : : protocol ( ) - > PHN ;
else if ( status = = " LUN " )
return MSNProtocol : : protocol ( ) - > LUN ;
else if ( status = = " BRB " )
return MSNProtocol : : protocol ( ) - > BRB ;
else if ( status = = " AWY " )
return MSNProtocol : : protocol ( ) - > AWY ;
else if ( status = = " BSY " )
return MSNProtocol : : protocol ( ) - > BSY ;
else if ( status = = " IDL " )
return MSNProtocol : : protocol ( ) - > IDL ;
else
return MSNProtocol : : protocol ( ) - > UNK ;
}
# include "msnnotifysocket.moc"
// vim: set noet ts=4 sts=4 sw=4: