From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- miranda-wine/protocols/MSN/msn_svcs.cpp | 1404 +++++++++++++++++++++++++++++++ 1 file changed, 1404 insertions(+) create mode 100644 miranda-wine/protocols/MSN/msn_svcs.cpp (limited to 'miranda-wine/protocols/MSN/msn_svcs.cpp') diff --git a/miranda-wine/protocols/MSN/msn_svcs.cpp b/miranda-wine/protocols/MSN/msn_svcs.cpp new file mode 100644 index 0000000..1faac95 --- /dev/null +++ b/miranda-wine/protocols/MSN/msn_svcs.cpp @@ -0,0 +1,1404 @@ +/* +Plugin of Miranda IM for communicating with users of the MSN Messenger protocol. +Copyright (c) 2003-5 George Hazan. +Copyright (c) 2002-3 Richard Hughes (original version). + +Miranda IM: the free icq client for MS Windows +Copyright (C) 2000-2002 Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "msn_global.h" + +#include +#include +#include + +#include "resource.h" + +void __cdecl MSNServerThread( ThreadData* info ); +void MSN_ChatStart(ThreadData* info); + +void msnftp_sendAcceptReject( filetransfer *ft, bool acc ); + +HANDLE msnBlockMenuItem = NULL; +extern char* profileURL; + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnAddToList - adds contact to the server list + +static HANDLE AddToListByEmail( const char *email, DWORD flags ) +{ + char urlEmail[ 255 ], *szProto; + UrlEncode( email, urlEmail, sizeof( urlEmail )); + HANDLE hContact; + + //check not already on list + for ( hContact = ( HANDLE )MSN_CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ); + hContact != NULL; + hContact = ( HANDLE )MSN_CallService( MS_DB_CONTACT_FINDNEXT, ( WPARAM )hContact, 0 )) + { + szProto = ( char* )MSN_CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact, 0 ); + if ( szProto != NULL && !strcmp( szProto, msnProtocolName )) { + char tEmail[ MSN_MAX_EMAIL_LEN ]; + if ( MSN_GetStaticString( "e-mail", hContact, tEmail, sizeof( tEmail ))) + continue; + + if ( strcmp( tEmail, email )) + continue; + + if ( !( flags & PALF_TEMPORARY ) && DBGetContactSettingByte( hContact, "CList", "NotOnList", 1 )) { + DBDeleteContactSetting( hContact, "CList", "NotOnList" ); + DBDeleteContactSetting( hContact, "CList", "Hidden" ); +LBL_AddContact: + if ( msnLoggedIn ) { + MSN_AddUser( hContact, urlEmail, LIST_FL ); + MSN_AddUser( hContact, urlEmail, LIST_BL + LIST_REMOVE ); + MSN_AddUser( hContact, urlEmail, LIST_AL ); + } + else hContact = NULL; + } + + return hContact; + } } + + //not already there: add + hContact = ( HANDLE )MSN_CallService( MS_DB_CONTACT_ADD, 0, 0 ); + MSN_CallService( MS_PROTO_ADDTOCONTACT, ( WPARAM )hContact,( LPARAM )msnProtocolName ); + MSN_SetString( hContact, "e-mail", email ); + + if ( !( flags & PALF_TEMPORARY )) + goto LBL_AddContact; + + DBWriteContactSettingByte( hContact, "CList", "NotOnList", 1 ); + DBWriteContactSettingByte( hContact, "CList", "Hidden", 1 ); + return hContact; +} + +static int MsnAddToList(WPARAM wParam,LPARAM lParam) +{ + PROTOSEARCHRESULT *psr=(PROTOSEARCHRESULT*)lParam; + + if ( psr->cbSize != sizeof( PROTOSEARCHRESULT )) + return NULL; + + return ( int )AddToListByEmail( psr->email, wParam ); +} + +static int MsnAddToListByEvent(WPARAM wParam, LPARAM lParam) +{ + DBEVENTINFO dbei = {0}; + dbei.cbSize = sizeof(dbei); + if (( dbei.cbBlob = MSN_CallService( MS_DB_EVENT_GETBLOBSIZE, lParam, 0 )) == (DWORD)(-1)) + return 0; + + dbei.pBlob=(PBYTE) alloca(dbei.cbBlob); + if ( MSN_CallService(MS_DB_EVENT_GET, lParam, ( LPARAM )&dbei)) return 0; + if ( strcmp(dbei.szModule, msnProtocolName)) return 0; + if ( dbei.eventType != EVENTTYPE_AUTHREQUEST) return 0; + + char* nick = (char *) (dbei.pBlob + sizeof(DWORD) + sizeof(HANDLE)); + char* firstName = nick + strlen(nick) + 1; + char* lastName = firstName + strlen(firstName) + 1; + char* email = lastName + strlen(lastName) + 1; + + return ( int ) AddToListByEmail( email, 0 ); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnAuthAllow - called after successful authorization + +static int MsnAuthAllow(WPARAM wParam,LPARAM lParam) +{ + if ( !msnLoggedIn ) + return 1; + + DBEVENTINFO dbei; + memset( &dbei, 0, sizeof( dbei )); + dbei.cbSize = sizeof( dbei ); + + if (( dbei.cbBlob = MSN_CallService( MS_DB_EVENT_GETBLOBSIZE, wParam, 0 )) == -1 ) + return 1; + + dbei.pBlob = ( PBYTE )alloca( dbei.cbBlob ); + if ( MSN_CallService( MS_DB_EVENT_GET, wParam, ( LPARAM )&dbei )) + return 1; + + if ( dbei.eventType != EVENTTYPE_AUTHREQUEST ) + return 1; + + if ( strcmp( dbei.szModule, msnProtocolName )) + return 1; + + char* nick = ( char* )( dbei.pBlob + sizeof( DWORD )*2 ); + char* firstName = nick + strlen( nick ) + 1; + char* lastName = firstName + strlen( firstName ) + 1; + char* email = lastName + strlen( lastName ) + 1; + + char urlNick[388],urlEmail[130]; + + UrlEncode( UTF8( nick ), urlNick, sizeof( urlNick )); + UrlEncode( email, urlEmail, sizeof( urlEmail )); + + AddToListByEmail( email, 0 ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnAuthDeny - called after unsuccessful authorization + +static int MsnAuthDeny(WPARAM wParam,LPARAM lParam) +{ + if ( !msnLoggedIn ) + return 1; + + DBEVENTINFO dbei; + memset( &dbei, 0, sizeof( dbei )); + dbei.cbSize = sizeof( dbei ); + + if (( dbei.cbBlob = MSN_CallService( MS_DB_EVENT_GETBLOBSIZE, wParam, 0 )) == -1 ) + return 1; + + dbei.pBlob = ( PBYTE )alloca( dbei.cbBlob ); + if ( MSN_CallService( MS_DB_EVENT_GET, wParam, ( LPARAM )&dbei )) + return 1; + + if ( dbei.eventType != EVENTTYPE_AUTHREQUEST ) + return 1; + + if ( strcmp( dbei.szModule, msnProtocolName )) + return 1; + + char* nick = ( char* )( dbei.pBlob + sizeof( DWORD )*2 ); + char* firstName = nick + strlen( nick ) + 1; + char* lastName = firstName + strlen( firstName ) + 1; + char* email = lastName + strlen( lastName ) + 1; + + char urlNick[388],urlEmail[130]; + + UrlEncode( UTF8(nick), urlNick, sizeof( urlNick )); + UrlEncode( email, urlEmail, sizeof( urlEmail )); + + MSN_AddUser( NULL, urlEmail, LIST_BL ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnBasicSearch - search contacts by e-mail + +static int MsnBasicSearch(WPARAM wParam,LPARAM lParam) +{ + if ( !msnLoggedIn || msnSearchID != -1 ) + return 0; + + char tEmail[ 256 ]; + if ( !MSN_GetStaticString( "e-mail", NULL, tEmail, sizeof tEmail )) { + if ( !stricmp(( char* )lParam, tEmail )) { + MSN_ShowError( "You cannot add yourself to the contact list" ); + return 0; + } } + + UrlEncode(( char* )lParam, tEmail, sizeof( tEmail )); + return msnSearchID = msnNsThread->sendPacket( "ADC", "BL N=%s", tEmail ); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Block command callback function + +static int MsnBlockCommand( WPARAM wParam, LPARAM lParam ) +{ + if ( msnLoggedIn ) { + char tEmail[ MSN_MAX_EMAIL_LEN ]; + if ( !MSN_GetStaticString( "e-mail", ( HANDLE )wParam, tEmail, sizeof( tEmail ))) + MSN_SetWord(( HANDLE )wParam, "ApparentMode", ( Lists_IsInList( LIST_BL, tEmail )) ? 0 : ID_STATUS_OFFLINE ); + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnContactDeleted - called when a contact is deleted from list + +static int MsnContactDeleted( WPARAM wParam, LPARAM lParam ) +{ + if ( !msnLoggedIn ) //should never happen for MSN contacts + return 0; + + char* szProto = ( char* )MSN_CallService( MS_PROTO_GETCONTACTBASEPROTO, wParam, 0 ); + if ( szProto == NULL || strcmp( szProto, msnProtocolName )) + return 0; + + HANDLE hContact = ( HANDLE )wParam; + char tEmail[ MSN_MAX_EMAIL_LEN ]; + if ( !MSN_GetStaticString( "e-mail", hContact, tEmail, sizeof( tEmail ))) { + MSN_AddUser( hContact, tEmail, LIST_FL | LIST_REMOVE ); + MSN_AddUser( hContact, tEmail, LIST_AL | LIST_REMOVE ); + + if ( !Lists_IsInList( LIST_RL, tEmail )) { + MSN_AddUser( hContact, tEmail, LIST_BL | LIST_REMOVE ); + Lists_Remove( 0xFF, tEmail ); + } + else { + MSN_AddUser( hContact, tEmail, LIST_BL ); + Lists_Remove( LIST_FL, tEmail ); + } } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnDbSettingChanged - look for contact's settings changes + +static int MsnDbSettingChanged(WPARAM wParam,LPARAM lParam) +{ + HANDLE hContact = ( HANDLE )wParam; + DBCONTACTWRITESETTING* cws = ( DBCONTACTWRITESETTING* )lParam; + + if ( !msnLoggedIn ) + return 0; + + if ( hContact == NULL && MyOptions.ManageServer && !strcmp( cws->szModule, "CListGroups" )) { + int iNumber = atol( cws->szSetting ); + LPCSTR szId = MSN_GetGroupByNumber( iNumber ); + if ( szId == NULL ) { + if ( cws->value.type == DBVT_ASCIIZ ) + MSN_AddServerGroup( cws->value.pszVal+1 ); + return 0; + } + + switch ( cws->value.type ) { + case DBVT_DELETED: msnNsThread->sendPacket( "RMG", szId ); break; + case DBVT_UTF8: MSN_RenameServerGroup( iNumber, szId, cws->value.pszVal+1 ); break; + case DBVT_ASCIIZ: MSN_RenameServerGroup( iNumber, szId, UTF8( cws->value.pszVal+1 )); break; + } + return 0; + } + + if ( !strcmp( cws->szSetting, "ApparentMode" )) { + char tEmail[ MSN_MAX_EMAIL_LEN ]; + if ( !MSN_GetStaticString( "e-mail", hContact, tEmail, sizeof( tEmail ))) { + int isBlocked = Lists_IsInList( LIST_BL, tEmail ); + + if ( !isBlocked && cws->value.wVal == ID_STATUS_OFFLINE ) { + MSN_AddUser( hContact, tEmail, LIST_AL + LIST_REMOVE ); + MSN_AddUser( hContact, tEmail, LIST_BL ); + } + else if ( isBlocked && cws->value.wVal == 0 ) { + MSN_AddUser( hContact, tEmail, LIST_BL + LIST_REMOVE ); + MSN_AddUser( hContact, tEmail, LIST_AL ); + } } } + + if ( !strcmp( cws->szModule, "CList" ) && MyOptions.ManageServer ) { + char* szProto = ( char* )MSN_CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM ) hContact, 0 ); + if ( szProto == NULL || strcmp( szProto, msnProtocolName )) + return 0; + + if ( !strcmp( cws->szSetting, "Group" )) { + switch( cws->value.type ) { + case DBVT_DELETED: MSN_MoveContactToGroup( hContact, NULL ); break; + case DBVT_ASCIIZ: MSN_MoveContactToGroup( hContact, UTF8(cws->value.pszVal)); break; + case DBVT_UTF8: MSN_MoveContactToGroup( hContact, cws->value.pszVal ); break; + } + return 0; + } + + if ( !strcmp( cws->szSetting, "MyHandle" )) { + char szContactID[ 100 ], szNewNick[ 387 ]; + if ( !MSN_GetStaticString( "ID", hContact, szContactID, sizeof( szContactID ))) { + if ( cws->value.type != DBVT_DELETED ) { + if ( cws->value.type == DBVT_UTF8 ) + UrlEncode( cws->value.pszVal, szNewNick, sizeof( szNewNick )); + else + UrlEncode( UTF8(cws->value.pszVal), szNewNick, sizeof( szNewNick )); + msnNsThread->sendPacket( "SBP", "%s MFN %s", szContactID, szNewNick ); + } + else { + MSN_GetStaticString( "e-mail", hContact, szNewNick, sizeof( szNewNick )); + msnNsThread->sendPacket( "SBP", "%s MFN %s", szContactID, szNewNick ); + } + return 0; + } } } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnEditProfile - goes to the Profile section at the Hotmail.com + +static int MsnEditProfile( WPARAM, LPARAM ) +{ + char tUrl[ 4096 ]; + mir_snprintf( tUrl, sizeof( tUrl ), "%s&did=1&t=%s&js=yes", profileURL, MSPAuth ); + MSN_CallService( MS_UTILS_OPENURL, TRUE, ( LPARAM )tUrl ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnFileAllow - starts the file transfer + +static void __cdecl MsnFileAckThread( void* arg ) +{ + filetransfer* ft = (filetransfer*)arg; + if ( !ft->inmemTransfer ) + { + char filefull[ MAX_PATH ]; + mir_snprintf( filefull, sizeof filefull, "%s\\%s", ft->std.workingDir, ft->std.currentFile ); + replaceStr( ft->std.currentFile, filefull ); + + if ( MSN_SendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, ft, ( LPARAM )&ft->std )) + return; + + if ( ft->wszFileName != NULL ) { + free( ft->wszFileName ); + ft->wszFileName = NULL; + } } + + bool fcrt = ft->create() != -1; + + if ( ft->p2p_appID != 0) + p2p_sendStatus( ft, MSN_GetThreadByID( ft->mThreadId ), fcrt ? 200 : 603 ); + else + msnftp_sendAcceptReject (ft, fcrt); + + MSN_SendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ft, 0); +} + +int MsnFileAllow(WPARAM wParam, LPARAM lParam) +{ + if ( !msnLoggedIn ) + return 0; + + CCSDATA* ccs = ( CCSDATA* )lParam; + filetransfer* ft = ( filetransfer* )ccs->wParam; + + if (( ft->std.workingDir = strdup(( char* )ccs->lParam )) == NULL ) { + char szCurrDir[ MAX_PATH ]; + GetCurrentDirectoryA( sizeof( szCurrDir ), szCurrDir ); + ft->std.workingDir = strdup( szCurrDir ); + } + else { + int len = strlen( ft->std.workingDir )-1; + if ( ft->std.workingDir[ len ] == '\\' ) + ft->std.workingDir[ len ] = 0; + } + + MSN_StartThread( MsnFileAckThread, ft ); + + return int( ft ); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnFileCancel - cancels the active file transfer + +int MsnFileCancel(WPARAM wParam, LPARAM lParam) +{ + CCSDATA* ccs = ( CCSDATA* )lParam; + filetransfer* ft = ( filetransfer* )ccs->wParam; + + if ( ft->hWaitEvent != INVALID_HANDLE_VALUE ) + SetEvent( ft->hWaitEvent ); + + ThreadData* thread = MSN_GetThreadByID( ft->mThreadId ); + if (!ft->std.sending && ft->fileId == -1) + { + if ( ft->p2p_appID != 0 ) + p2p_sendStatus(ft, thread, 603); + else + msnftp_sendAcceptReject (ft, false); + } + else + { + if ( ft->p2p_appID != 0 ) + p2p_sendCancel( thread, ft ); + else + ft->bCanceled = true; + } + + ft->std.files = NULL; + ft->std.totalFiles = 0; + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnFileDeny - rejects the file transfer request + +int MsnFileDeny( WPARAM wParam, LPARAM lParam ) +{ + if ( !msnLoggedIn ) + return 1; + + CCSDATA* ccs = ( CCSDATA* )lParam; + filetransfer* ft = ( filetransfer* )ccs->wParam; + + if ( ft->p2p_appID != 0 ) + p2p_sendStatus( ft, MSN_GetThreadByID(ft->mThreadId), 603 ); + else + msnftp_sendAcceptReject (ft, false); + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnFileResume - renames a file + +int MsnFileResume( WPARAM wParam, LPARAM lParam ) +{ + filetransfer* ft = ( filetransfer* )wParam; + if ( !msnLoggedIn || ft == NULL ) + return 1; + + PROTOFILERESUME *pfr = (PROTOFILERESUME*)lParam; + switch (pfr->action) + { + case FILERESUME_SKIP: + if ( ft->p2p_appID != 0 ) + p2p_sendStatus( ft, MSN_GetThreadByID( ft->mThreadId ), 603 ); + else + msnftp_sendAcceptReject (ft, false); + break; + + case FILERESUME_RENAME: + if ( ft->wszFileName != NULL ) { + free( ft->wszFileName ); + ft->wszFileName = NULL; + } + replaceStr( ft->std.currentFile, pfr->szFilename ); + + default: + bool fcrt = ft->create() != -1; + if ( ft->p2p_appID != 0 ) + p2p_sendStatus( ft, MSN_GetThreadByID( ft->mThreadId ), fcrt ? 200 : 603 ); + else + msnftp_sendAcceptReject (ft, fcrt); + + MSN_SendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ft, 0); + break; + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnGetAvatarInfo - retrieve the avatar info + +static int MsnGetAvatarInfo(WPARAM wParam,LPARAM lParam) +{ + PROTO_AVATAR_INFORMATION* AI = ( PROTO_AVATAR_INFORMATION* )lParam; + + if ( !MyOptions.EnableAvatars || ( MSN_GetDword( AI->hContact, "FlagBits", 0 ) & 0x40000000 ) == 0 ) + return GAIR_NOAVATAR; + + char szContext[ MAX_PATH ]; + if ( MSN_GetStaticString(( AI->hContact == NULL ) ? "PictObject" : "PictContext", AI->hContact, szContext, sizeof szContext )) + return GAIR_NOAVATAR; + + MSN_GetAvatarFileName( AI->hContact, AI->filename, sizeof AI->filename ); + AI->format = ( AI->hContact == NULL ) ? PA_FORMAT_PNG : PA_FORMAT_BMP; + + if ( ::access( AI->filename, 0 ) == 0 ) { + char szSavedContext[ 256 ]; + if ( !MSN_GetStaticString( "PictSavedContext", AI->hContact, szSavedContext, sizeof szSavedContext )) + if ( !strcmp( szSavedContext, szContext )) + return GAIR_SUCCESS; + } + + if (( wParam & GAIF_FORCE ) != 0 && AI->hContact != NULL ) { + p2p_invite( AI->hContact, MSN_APPID_AVATAR ); + return GAIR_WAITFOR; + } + + return GAIR_NOAVATAR; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnGetAwayMsg - reads the current status message for a user + +static void __cdecl MsnGetAwayMsgThread( HANDLE hContact ) +{ + DBVARIANT dbv; + if ( !DBGetContactSetting( hContact, "CList", "StatusMsg", &dbv )) { + MSN_SendBroadcast( hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, ( HANDLE )1, ( LPARAM )dbv.pszVal ); + MSN_FreeVariant( &dbv ); + } + else MSN_SendBroadcast( hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, ( HANDLE )1, ( LPARAM )0 ); +} + +static int MsnGetAwayMsg(WPARAM wParam,LPARAM lParam) +{ + CCSDATA* ccs = ( CCSDATA* )lParam; + MSN_StartThread( MsnGetAwayMsgThread, ccs->hContact ); + return 1; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnGetCaps - obtain the protocol capabilities + +static int MsnGetCaps(WPARAM wParam,LPARAM lParam) +{ + switch( wParam ) { + case PFLAGNUM_1: + { int result = PF1_IM | PF1_SERVERCLIST | PF1_AUTHREQ | PF1_BASICSEARCH | + PF1_ADDSEARCHRES | PF1_SEARCHBYEMAIL | PF1_USERIDISEMAIL | + PF1_FILESEND | PF1_FILERECV | PF1_URLRECV | PF1_VISLIST; + if ( MyOptions.UseMSNP11 ) + result |= PF1_MODEMSG; + return result; + } + case PFLAGNUM_2: + return PF2_ONLINE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | + PF2_ONTHEPHONE | PF2_OUTTOLUNCH | PF2_INVISIBLE; + + case PFLAGNUM_3: + return PF2_ONLINE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | + PF2_ONTHEPHONE | PF2_OUTTOLUNCH; + + case PFLAGNUM_4: + return PF4_SUPPORTTYPING | PF4_AVATARS; + + case PFLAG_UNIQUEIDTEXT: + return ( int )MSN_Translate( "E-mail address" ); + + case PFLAG_UNIQUEIDSETTING: + return ( int )"e-mail"; + + case PFLAG_MAXLENOFMESSAGE: + return 1202; + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnGetInfo - nothing to do, cause we cannot obtain information from the server + +HANDLE msnGetInfoContact = NULL; + +static int MsnGetInfo(WPARAM wParam,LPARAM lParam) +{ + if ( !msnLoggedIn ) + return 0; + + CCSDATA *ccs=(CCSDATA*)lParam; + msnGetInfoContact = ccs->hContact; + msnNsThread->send( "PNG\r\n", 5 ); + return 1; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnGetName - obtain the protocol name + +static int MsnGetName( WPARAM wParam, LPARAM lParam ) +{ + lstrcpynA(( char* )lParam, msnProtocolName, wParam ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnGetStatus - obtain the protocol status + +static int MsnGetStatus(WPARAM wParam,LPARAM lParam) +{ + return msnStatusMode; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnGotoInbox - goes to the Inbox folder at the Hotmail.com + +static int MsnGotoInbox( WPARAM, LPARAM ) +{ + DWORD tThreadID; + CreateThread( NULL, 0, MsnShowMailThread, NULL, 0, &tThreadID ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnInviteCommand - invite command callback function + +static int MsnInviteCommand( WPARAM wParam, LPARAM lParam ) +{ + ThreadData* tActiveThreads[ 64 ]; + int tThreads = MSN_GetActiveThreads( tActiveThreads ), tChosenThread; +// modified for chat + + + switch( tThreads ) { + case 0: + MessageBoxA(NULL, Translate("No active chat session is found."), Translate("MSN Chat"), MB_OK|MB_ICONINFORMATION); + return 0; + + case 1: + tChosenThread = 0; + break; + + default: + HMENU tMenu = ::CreatePopupMenu(); + + for ( int i=0; i < tThreads; i++ ) { + if (( long )tActiveThreads[i]->mJoinedContacts[0] < 0 ) { + char sessionName[ 255 ]; + mir_snprintf( sessionName, sizeof( sessionName ), "%s%s", + Translate( "MSN Chat #" ), tActiveThreads[i]->mChatID ); + ::AppendMenuA( tMenu, MF_STRING, ( UINT_PTR )( i+1 ), sessionName ); + } + else ::AppendMenu( tMenu, MF_STRING, ( UINT_PTR )( i+1 ), MSN_GetContactNameT( *tActiveThreads[i]->mJoinedContacts )); + } + + HWND tWindow = CreateWindow(_T("EDIT"),_T(""),0,1,1,1,1,NULL,NULL,hInst,NULL); + + POINT pt; + ::GetCursorPos ( &pt ); + tChosenThread = ::TrackPopupMenu( tMenu, TPM_NONOTIFY | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, tWindow, NULL ); + ::DestroyMenu( tMenu ); + ::DestroyWindow( tWindow ); + if ( !tChosenThread ) + return 0; + + tChosenThread--; + } + + char tEmail[ MSN_MAX_EMAIL_LEN ]; + if ( !MSN_GetStaticString( "e-mail", ( HANDLE )wParam, tEmail, sizeof( tEmail ))) { + for ( int j=0; j < tActiveThreads[ tChosenThread ]->mJoinedCount; j++ ) { + // if the user is already in the chat session + if ( tActiveThreads[ tChosenThread ]->mJoinedContacts[j] == ( HANDLE )wParam ) { + MessageBoxA(NULL, Translate("User is already in the chat session."), Translate("MSN Chat"), MB_OK|MB_ICONINFORMATION); + return 0; + } } + + tActiveThreads[ tChosenThread ]->sendPacket( "CAL", tEmail ); + + if ( msnHaveChatDll ) + MSN_ChatStart(tActiveThreads[ tChosenThread ]); + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnLoadIcon - obtain the protocol icon + +static int MsnLoadIcon(WPARAM wParam,LPARAM lParam) +{ + UINT id; + + switch(wParam&0xFFFF) { + case PLI_PROTOCOL: id=IDI_MSN; break; + default: return (int)(HICON)NULL; + } + + bool tIsSmall = ( wParam & PLIF_SMALL ) != 0; + return (int)LoadImage( hInst, MAKEINTRESOURCE(id), IMAGE_ICON, + GetSystemMetrics(tIsSmall ? SM_CXSMICON : SM_CXICON), + GetSystemMetrics(tIsSmall ? SM_CYSMICON : SM_CYICON), 0 ); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnRebuildContactMenu - gray or ungray the block menus according to contact's status + +static int MsnRebuildContactMenu( WPARAM wParam, LPARAM lParam ) +{ + char szEmail[ MSN_MAX_EMAIL_LEN ]; + if ( !MSN_GetStaticString( "e-mail", ( HANDLE )wParam, szEmail, sizeof szEmail )) { + CLISTMENUITEM clmi = { 0 }; + clmi.cbSize = sizeof( clmi ); + clmi.pszName = MSN_Translate( ( Lists_IsInList( LIST_BL, szEmail ) ? "&Unblock" : "&Block" )); + clmi.flags = CMIM_NAME; + MSN_CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )msnBlockMenuItem, ( LPARAM )&clmi ); + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnRecvFile - creates a database event from the file request been received + +int MsnRecvFile( WPARAM wParam, LPARAM lParam ) +{ + CCSDATA* ccs = ( CCSDATA* )lParam; + DBDeleteContactSetting( ccs->hContact, "CList", "Hidden" ); + + ThreadData* thread = MSN_GetThreadByContact( ccs->hContact ); + if ( thread == NULL ) + { msnNsThread->sendPacket( "XFR", "SB" ); + return 0; + } + + PROTORECVEVENT* pre = ( PROTORECVEVENT* )ccs->lParam; + char* szFile = pre->szMessage + sizeof( DWORD ); + char* szDescr = szFile + strlen( szFile ) + 1; + + DBEVENTINFO dbei; + memset( &dbei, 0, sizeof( dbei )); + dbei.cbSize = sizeof( dbei ); + dbei.szModule = msnProtocolName; + dbei.timestamp = pre->timestamp; + dbei.flags = ( pre->flags & PREF_CREATEREAD ) ? DBEF_READ : 0; + dbei.eventType = EVENTTYPE_FILE; + dbei.cbBlob = sizeof( DWORD ) + strlen( szFile ) + strlen( szDescr ) + 2; + dbei.pBlob = ( PBYTE )pre->szMessage; + MSN_CallService( MS_DB_EVENT_ADD, ( WPARAM )ccs->hContact, ( LPARAM )&dbei ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnRecvMessage - creates a database event from the message been received + +static int MsnRecvMessage(WPARAM wParam,LPARAM lParam) +{ + CCSDATA* ccs = ( CCSDATA* )lParam; + PROTORECVEVENT* pre = ( PROTORECVEVENT* )ccs->lParam; + + DBDeleteContactSetting( ccs->hContact, "CList", "Hidden" ); + + DBEVENTINFO dbei = { 0 }; + dbei.cbSize = sizeof( dbei ); + dbei.szModule = msnProtocolName; + dbei.timestamp = pre->timestamp; + dbei.flags = ( pre->flags & PREF_CREATEREAD ) ? DBEF_READ : 0; + if ( pre->flags & PREF_RTL ) + dbei.flags |= DBEF_RTL; + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.cbBlob = strlen( pre->szMessage )+1; + if ( pre->flags & PREF_UNICODE ) + dbei.cbBlob *= ( sizeof( wchar_t )+1 ); + + dbei.pBlob = ( PBYTE )pre->szMessage; + MSN_CallService( MS_DB_EVENT_ADD, ( WPARAM )ccs->hContact, ( LPARAM )&dbei ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnSendFile - initiates a file transfer + +static int MsnSendFile( WPARAM wParam, LPARAM lParam ) +{ + if ( !msnLoggedIn ) + return 0; + + CCSDATA *ccs = ( CCSDATA* )lParam; + if ( MSN_GetWord( ccs->hContact, "Status", ID_STATUS_OFFLINE ) == ID_STATUS_OFFLINE ) + return 0; + + char** files = ( char** )ccs->lParam; + if ( files[1] != NULL ) { + MSN_ShowError( Translate( "MSN protocol allows only one file to be sent at a time" )); + return 0; + } + + long tFileSize = 0; + { struct _stat statbuf; + if ( _stat( files[0], &statbuf ) == 0 ) + tFileSize += statbuf.st_size; + } + + filetransfer* sft = new filetransfer(); + sft->std.totalFiles = 1; + sft->std.files = files; + sft->std.currentFile = strdup( files[0] ); + sft->std.totalBytes = sft->std.currentFileSize = tFileSize; + sft->std.hContact = ccs->hContact; + sft->std.sending = 1; + sft->std.currentFileNumber = 0; + + sft->fileId = _open( sft->std.currentFile, _O_BINARY | _O_RDONLY, _S_IREAD ); + MSN_DebugLog( "Unable to open file '%s', error %d", sft->std.currentFile, errno ); + if ( sft->fileId == -1 ) return NULL; + + DWORD dwFlags = MSN_GetDword( ccs->hContact, "FlagBits", 0 ); + if ( dwFlags & 0x70000000 ) + p2p_invite( ccs->hContact, MSN_APPID_FILE, sft ); + else { + ThreadData* thread = MSN_GetThreadByContact( ccs->hContact ); + if ( thread != NULL ) { + thread->mMsnFtp = sft; + sft->mThreadId = thread->mUniqueID; + } + else msnNsThread->sendPacket( "XFR", "SB" ); + + char* pszFiles = strrchr( *files, '\\' ), msg[ 1024 ]; + if ( pszFiles ) + pszFiles++; + else + pszFiles = *files; + + mir_snprintf( msg, sizeof( msg ), + "Content-Type: text/x-msmsgsinvite; charset=UTF-8\r\n\r\n" + "Application-Name: File Transfer\r\n" + "Application-GUID: {5D3E02AB-6190-11d3-BBBB-00C04F795683}\r\n" + "Invitation-Command: INVITE\r\n" + "Invitation-Cookie: %i\r\n" + "Application-File: %s\r\n" + "Application-FileSize: %i\r\n\r\n", + ( WORD )(((double)rand()/(double)RAND_MAX)*4294967295), UTF8(pszFiles), tFileSize ); + + if ( thread == NULL ) + MsgQueue_Add( ccs->hContact, 'S', msg, -1, sft ); + else + thread->sendMessage( 'S', msg, MSG_DISABLE_HDR ); + } + + MSN_SendBroadcast( ccs->hContact, ACKTYPE_FILE, ACKRESULT_SENTREQUEST, sft, 0 ); + return (int)(HANDLE)sft; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnSendMessage - sends the message to a server + +struct TFakeAckParams +{ + inline TFakeAckParams( HANDLE p1, HANDLE p2, LONG p3, LPCSTR p4 ) : + hEvent( p1 ), + hContact( p2 ), + id( p3 ), + msg( p4 ) + {} + + HANDLE hEvent; + HANDLE hContact; + LONG id; + LPCSTR msg; +}; + +static DWORD CALLBACK sttFakeAck( LPVOID param ) +{ + TFakeAckParams* tParam = ( TFakeAckParams* )param; + WaitForSingleObject( tParam->hEvent, INFINITE ); + + Sleep( 100 ); + if ( tParam->msg == NULL ) + MSN_SendBroadcast( tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, ( HANDLE )tParam->id, 0 ); + else + MSN_SendBroadcast( tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, ( HANDLE )tParam->id, LPARAM( tParam->msg )); + + CloseHandle( tParam->hEvent ); + delete tParam; + return 0; +} + +static int MsnSendMessage( WPARAM wParam, LPARAM lParam ) +{ + CCSDATA* ccs = ( CCSDATA* )lParam; + char *msg, *errMsg = NULL; + + if ( ccs->wParam & PREF_UNICODE ) { + char* p = ( char* )ccs->lParam; + msg = Utf8EncodeUcs2(( wchar_t* )&p[ strlen(p)+1 ] ); + } + else msg = Utf8Encode(( char* )ccs->lParam ); + + if ( strlen( msg ) > 1202 ) { + errMsg = MSN_Translate( "Message is too long: MSN messages are limited by 1202 UTF8 chars" ); +LBL_Error: + free( msg ); + + HANDLE hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); + DWORD dwThreadId; + CloseHandle( CreateThread( NULL, 0, sttFakeAck, new TFakeAckParams( hEvent, ccs->hContact, 999999, errMsg ), 0, &dwThreadId )); + SetEvent( hEvent ); + return 999999; + } + + int seq, msgType = ( MyOptions.SlowSend ) ? 'A' : 'N'; + int rtlFlag = ( ccs->wParam & PREF_RTL ) ? MSG_RTL : 0; + ThreadData* thread = MSN_GetThreadByContact( ccs->hContact ); + if ( thread == NULL ) + { + WORD wStatus = MSN_GetWord( ccs->hContact, "Status", ID_STATUS_OFFLINE ); + if ( wStatus == ID_STATUS_OFFLINE || msnStatusMode == ID_STATUS_INVISIBLE ) { + errMsg = MSN_Translate( "MSN protocol does not support offline messages" ); + goto LBL_Error; + } + + if ( MsgQueue_CheckContact( ccs->hContact ) == NULL ) + msnNsThread->sendPacket( "XFR", "SB" ); + + seq = MsgQueue_Add( ccs->hContact, msgType, msg, 0, 0, rtlFlag ); + } + else + { if ( thread->mJoinedCount == 0 ) + seq = MsgQueue_Add( ccs->hContact, msgType, msg, 0, 0, rtlFlag ); + else { + seq = thread->sendMessage( msgType, msg, rtlFlag ); + + if ( seq == -1 ) { + seq = MsgQueue_Add( ccs->hContact, msgType, msg, 0, 0, rtlFlag ); + msnNsThread->sendPacket( "XFR", "SB" ); + } + else if ( !MyOptions.SlowSend ) { + HANDLE hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); + DWORD dwThreadId; + CloseHandle( CreateThread( NULL, 0, sttFakeAck, new TFakeAckParams( hEvent, ccs->hContact, seq, 0 ), 0, &dwThreadId )); + SetEvent( hEvent ); + } } } + + free( msg ); + return seq; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnSendNudge - Sending a nudge + +static int MsnSendNudge( WPARAM wParam, LPARAM lParam ) +{ + if ( !msnLoggedIn ) return 0; + + HANDLE hContact = ( HANDLE )wParam; + char msg[ 1024 ]; + + mir_snprintf( msg, sizeof( msg ),"N 69\r\nMIME-Version: 1.0\r\n" + "Content-Type: text/x-msnmsgr-datacast\r\n\r\n" + "ID: 1\r\n\r\n"); + + ThreadData* thread = MSN_GetThreadByContact( hContact ); + + if ( thread == NULL ) { + if ( MsgQueue_CheckContact( hContact ) == NULL ) + { + MsgQueue_Add( hContact, 'N', msg, -1 ); + msnNsThread->sendPacket( "XFR", "SB" ); + } + } + else + thread->sendPacket( "MSG",msg); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnSendNetMeeting - Netmeeting callback function + +static int MsnSendNetMeeting( WPARAM wParam, LPARAM lParam ) +{ + if ( !msnLoggedIn ) return 0; + + ThreadData* thread = MSN_GetThreadByContact( HANDLE(wParam) ); + + if ( thread == NULL ) { + MessageBoxA( NULL, MSN_Translate( "You must be talking to start Netmeeting" ), "MSN Protocol", MB_OK | MB_ICONERROR ); + return 0; + } + + char msg[ 1024 ]; + + mir_snprintf( msg, sizeof( msg ), + "Content-Type: text/x-msmsgsinvite; charset=UTF-8\r\n\r\n" + "Application-Name: NetMeeting\r\n" + "Application-GUID: {44BBA842-CC51-11CF-AAFA-00AA00B6015C}\r\n" + "Session-Protocol: SM1\r\n" + "Invitation-Command: INVITE\r\n" + "Invitation-Cookie: %i\r\n" + "Session-ID: {1A879604-D1B8-11D7-9066-0003FF431510}\r\n\r\n", + ( WORD )(((double)rand()/(double)RAND_MAX)*4294967295)); + + thread->sendMessage( 'N', msg, MSG_DISABLE_HDR ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnSetApparentMode - controls contact visibility + +static int MsnSetApparentMode( WPARAM wParam, LPARAM lParam ) +{ + CCSDATA* ccs = ( CCSDATA* )lParam; + if ( ccs->wParam && ccs->wParam != ID_STATUS_OFFLINE ) + return 1; + + WORD oldMode = MSN_GetWord( ccs->hContact, "ApparentMode", 0 ); + if ( ccs->wParam != oldMode ) + MSN_SetWord( ccs->hContact, "ApparentMode", ( WORD )ccs->wParam ); + + return 1; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnSetAvatar - sets an avatar without UI + +static int MsnSetAvatar( WPARAM wParam, LPARAM lParam ) +{ + HBITMAP hBitmap = ( HBITMAP )MSN_CallService( MS_UTILS_LOADBITMAP, 0, lParam ); + if ( hBitmap == NULL ) + return 1; + + if (( hBitmap = MSN_StretchBitmap( hBitmap )) == NULL ) + return 2; + + MSN_SaveBitmapAsAvatar( hBitmap, (char *) lParam ); + DeleteObject( hBitmap ); + if ( msnLoggedIn ) + MSN_SetServerStatus( msnStatusMode ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnSetAvatar - sets an avatar without UI + +static int MsnSetAvatarUI( WPARAM wParam, LPARAM lParam ) +{ + char szFileName[ MAX_PATH ]; + if ( MSN_EnterBitmapFileName( szFileName ) != ERROR_SUCCESS ) + return 1; + + return MsnSetAvatar( 0, ( LPARAM )szFileName ); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnSetAwayMsg - sets the current status message for a user + +static int MsnSetAwayMsg(WPARAM wParam,LPARAM lParam) +{ + int i; + + for ( i=0; i < MSN_NUM_MODES; i++ ) + if ( msnModeMsgs[i].m_mode == (int)wParam ) + break; + + if ( i == MSN_NUM_MODES ) + return 1; + + replaceStr( msnModeMsgs[i].m_msg, ( char* )lParam ); + + if ( (int)wParam == msnDesiredStatus ) + MSN_SendStatusMessage(( char* )lParam ); + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// SetNickname - sets a nick name without UI + +static int MsnSetNickName( WPARAM wParam, LPARAM lParam ) +{ + MSN_SendNickname(( char* )lParam ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// SetNicknameCommand - sets nick name + +static BOOL CALLBACK DlgProcSetNickname(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch ( msg ) + { + case WM_INITDIALOG: + { + TranslateDialogDefault( hwndDlg ); + SendMessage( hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon( hInst, MAKEINTRESOURCE( IDI_MSN ))); + SendMessage( GetDlgItem( hwndDlg, IDC_NICKNAME ), EM_LIMITTEXT, 129, 0 ); + + DBVARIANT dbv; + if ( !DBGetContactSettingTString( NULL, msnProtocolName, "Nick", &dbv )) { + SetDlgItemText( hwndDlg, IDC_NICKNAME, dbv.ptszVal ); + MSN_FreeVariant( &dbv ); + } + return TRUE; + } + case WM_COMMAND: + switch(wParam) + { + case IDOK: + if ( msnLoggedIn ) { + TCHAR str[ 130 ]; + GetDlgItemText( hwndDlg, IDC_NICKNAME, str, SIZEOF( str )); + MSN_SendNicknameT( str ); + } + + case IDCANCEL: + DestroyWindow( hwndDlg ); + break; + } + break; + + case WM_CLOSE: + DestroyWindow( hwndDlg ); + break; + } + return FALSE; +} + +static int SetNicknameUI( WPARAM wParam, LPARAM lParam ) +{ + HWND hwndSetNickname = CreateDialog(hInst, MAKEINTRESOURCE( IDD_SETNICKNAME ), NULL, DlgProcSetNickname ); + + SetForegroundWindow( hwndSetNickname ); + SetFocus( hwndSetNickname ); + ShowWindow( hwndSetNickname, SW_SHOW ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnSetStatus - set the plugin's connection status + +static int MsnSetStatus( WPARAM wParam, LPARAM lParam ) +{ + msnDesiredStatus = wParam; + MSN_DebugLog( "PS_SETSTATUS(%d,0)", wParam ); + + if ( msnDesiredStatus == ID_STATUS_OFFLINE ) + { + MSN_GoOffline(); + } + else if (!msnLoggedIn && !(msnStatusMode>=ID_STATUS_CONNECTING && msnStatusModemServer ) ]; + if ( MSN_GetStaticString( "LoginServer", NULL, tServer, sizeof( tServer ))) + strcpy( tServer, MSN_DEFAULT_LOGIN_SERVER ); + + mir_snprintf( newThread->mServer, sizeof( newThread->mServer ), "%s:%i", tServer, tServerPort ); + newThread->mServer[ sizeof(newThread->mServer)-1 ] = 0; + + newThread->mType = SERVER_DISPATCH; + newThread->mIsMainThread = true; + { int oldMode = msnStatusMode; + msnStatusMode = ID_STATUS_CONNECTING; + MSN_SendBroadcast( NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, ( HANDLE )oldMode, msnStatusMode ); + } + newThread->startThread(( pThreadFunc )MSNServerThread ); + } + else MSN_SetServerStatus( msnDesiredStatus ); + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnUserIsTyping - notify another contact that we're typing a message + +extern char sttHeaderStart[]; + +static int MsnUserIsTyping(WPARAM wParam, LPARAM lParam) +{ + if ( !msnLoggedIn || lParam == PROTOTYPE_SELFTYPING_OFF ) + return 0; + + char tEmail[ MSN_MAX_EMAIL_LEN ]; + if ( MSN_GetStaticString( "e-mail", NULL, tEmail, sizeof tEmail )) + return 0; + + HANDLE hContact = ( HANDLE )wParam; + WORD wStatus = MSN_GetWord( hContact, "Status", ID_STATUS_OFFLINE ); + if ( wStatus == ID_STATUS_OFFLINE || msnStatusMode == ID_STATUS_INVISIBLE ) + return 0; + + char tCommand[ 1024 ]; + mir_snprintf( tCommand, sizeof( tCommand ), + "Content-Type: text/x-msmsgscontrol\r\n" + "TypingUser: %s\r\n\r\n\r\n", tEmail ); + + ThreadData* T = MSN_GetThreadByContact( hContact ); + if ( T == NULL ) { + if ( MsgQueue_CheckContact( hContact ) == NULL ) { + MsgQueue_Add( hContact, 'U', tCommand, -1 ); + msnNsThread->sendPacket( "XFR", "SB" ); + } + } + else T->sendMessage( 'U', tCommand, MSG_DISABLE_HDR ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnViewProfile - view a contact's profile at http://members.msn.com + +static char sttUrlPrefix[] = "http://members.msn.com/"; + +static int MsnViewProfile( WPARAM wParam, LPARAM lParam ) +{ + char tUrl[ MSN_MAX_EMAIL_LEN + sizeof sttUrlPrefix ]; + strcpy( tUrl, sttUrlPrefix ); + + if ( !MSN_GetStaticString( "e-mail", ( HANDLE )wParam, tUrl + sizeof sttUrlPrefix - 1, MSN_MAX_EMAIL_LEN )) + MSN_CallService( MS_UTILS_OPENURL, 1, ( LPARAM )tUrl ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MsnViewServiceStatus - display MSN services status + +static int MsnViewServiceStatus( WPARAM wParam, LPARAM lParam ) +{ + MSN_CallService( MS_UTILS_OPENURL, 1, ( LPARAM )"http://messenger.msn.com/Status.aspx" ); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Services initialization and destruction + +static HANDLE hHookSettingChanged = NULL; +static HANDLE hHookContactDeleted = NULL; +static HANDLE hHookRebuildCMenu = NULL; + +int LoadMsnServices( void ) +{ + ////////////////////////////////////////////////////////////////////////////////////// + // Main menu initialization + + char servicefunction[ 100 ]; + strcpy( servicefunction, msnProtocolName ); + char* tDest = servicefunction + strlen( servicefunction ); + CLISTMENUITEM mi; + + if ( !MSN_GetByte( "DisableSetNickname", 0 )) + { + strcpy( tDest, MS_SET_NICKNAME_UI ); + CreateServiceFunction( servicefunction, SetNicknameUI ); + + memset( &mi, 0, sizeof( mi )); + mi.popupPosition = 500085000; + mi.pszPopupName = msnProtocolName; + mi.cbSize = sizeof( mi ); + mi.position = 2000060000; + mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MSN )); + mi.pszName = MSN_Translate( "Set &Nickname" ); + mi.pszService = servicefunction; + msnMenuItems[ 0 ] = ( HANDLE )MSN_CallService( MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi ); + + strcpy( tDest, MS_GOTO_INBOX ); + CreateServiceFunction( servicefunction, MsnGotoInbox ); + + mi.position = 2000060001; + mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_INBOX )); + mi.pszName = MSN_Translate( "Display Hotmail &Inbox" ); + mi.pszService = servicefunction; + MSN_CallService( MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi ); + + strcpy( tDest, MS_EDIT_PROFILE ); + CreateServiceFunction( servicefunction, MsnEditProfile ); + + mi.position = 2000060002; + mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_PROFILE )); + mi.pszName = MSN_Translate( "Edit MSN &Profile" ); + mi.pszService = servicefunction; + msnMenuItems[ 1 ] = ( HANDLE )MSN_CallService( MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi ); + + strcpy( tDest, MS_VIEW_STATUS ); + CreateServiceFunction( servicefunction, MsnViewServiceStatus ); + + mi.position = 2000060003; + mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_SERVICES )); + mi.pszName = MSN_Translate( "View MSN Services &Status" ); + mi.pszService = servicefunction; + MSN_CallService( MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi ); + + strcpy( tDest, MS_SET_AVATAR_UI ); + CreateServiceFunction( servicefunction, MsnSetAvatarUI ); + + mi.position = 2000060004; + mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_AVATAR )); + mi.pszName = MSN_Translate( "Set &Avatar" ); + mi.pszService = servicefunction; + MSN_CallService( MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&mi ); + } + + ////////////////////////////////////////////////////////////////////////////////////// + // Contact menu initialization + + strcpy( tDest, MSN_BLOCK ); + CreateServiceFunction( servicefunction, MsnBlockCommand ); + + memset( &mi, 0, sizeof( mi )); + mi.cbSize = sizeof( mi ); + mi.position = -500050000; + mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MSNBLOCK )); + mi.pszContactOwner = msnProtocolName; + mi.pszName = MSN_Translate( "&Block" ); + mi.pszService = servicefunction; + msnBlockMenuItem = ( HANDLE )MSN_CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, ( LPARAM )&mi ); + + strcpy( tDest, MSN_INVITE ); + CreateServiceFunction( servicefunction, MsnInviteCommand ); + + mi.flags = CMIF_NOTOFFLINE; + mi.position = -500050001; + mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_INVITE )); + mi.pszName = MSN_Translate( "&Invite to chat" ); + mi.pszService = servicefunction; + MSN_CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, ( LPARAM )&mi ); + + strcpy( tDest, MSN_NETMEETING ); + CreateServiceFunction( servicefunction, MsnSendNetMeeting ); + + mi.flags = CMIF_NOTOFFLINE; + mi.position = -500050002; + mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_NETMEETING )); + mi.pszName = MSN_Translate( "&Start Netmeeting" ); + mi.pszService = servicefunction; + MSN_CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, ( LPARAM )&mi ); + + strcpy( tDest, MSN_VIEW_PROFILE ); + CreateServiceFunction( servicefunction, MsnViewProfile ); + + mi.flags = 0; + mi.position = -500050003; + mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_PROFILE )); + mi.pszName = MSN_Translate( "&View Profile" ); + mi.pszService = servicefunction; + MSN_CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, ( LPARAM )&mi ); + + MSN_EnableMenuItems( FALSE ); + + ////////////////////////////////////////////////////////////////////////////////////// + // Service creation + + hHookContactDeleted = HookEvent( ME_DB_CONTACT_DELETED, MsnContactDeleted ); + hHookSettingChanged = HookEvent( ME_DB_CONTACT_SETTINGCHANGED, MsnDbSettingChanged ); + hHookRebuildCMenu = HookEvent( ME_CLIST_PREBUILDCONTACTMENU, MsnRebuildContactMenu ); + + MSN_CreateProtoServiceFunction( PS_ADDTOLIST, MsnAddToList ); + MSN_CreateProtoServiceFunction( PS_ADDTOLISTBYEVENT, MsnAddToListByEvent ); + MSN_CreateProtoServiceFunction( PS_AUTHALLOW, MsnAuthAllow ); + MSN_CreateProtoServiceFunction( PS_AUTHDENY, MsnAuthDeny ); + MSN_CreateProtoServiceFunction( PS_BASICSEARCH, MsnBasicSearch ); + MSN_CreateProtoServiceFunction( PS_FILERESUME, MsnFileResume ); + MSN_CreateProtoServiceFunction( PS_GETAVATARINFO, MsnGetAvatarInfo ); + MSN_CreateProtoServiceFunction( PS_GETCAPS, MsnGetCaps ); + MSN_CreateProtoServiceFunction( PS_GETNAME, MsnGetName ); + MSN_CreateProtoServiceFunction( PS_GETSTATUS, MsnGetStatus ); + MSN_CreateProtoServiceFunction( PS_LOADICON, MsnLoadIcon ); + MSN_CreateProtoServiceFunction( PS_SEARCHBYEMAIL, MsnBasicSearch ); + MSN_CreateProtoServiceFunction( PS_SETSTATUS, MsnSetStatus ); + + MSN_CreateProtoServiceFunction( PSR_FILE, MsnRecvFile ); + MSN_CreateProtoServiceFunction( PSR_MESSAGE, MsnRecvMessage ); + + MSN_CreateProtoServiceFunction( PSS_FILE, MsnSendFile ); + MSN_CreateProtoServiceFunction( PSS_FILEALLOW, MsnFileAllow ); + MSN_CreateProtoServiceFunction( PSS_FILECANCEL, MsnFileCancel ); + MSN_CreateProtoServiceFunction( PSS_FILEDENY, MsnFileDeny ); + MSN_CreateProtoServiceFunction( PSS_GETINFO, MsnGetInfo ); + MSN_CreateProtoServiceFunction( PSS_MESSAGE, MsnSendMessage ); + MSN_CreateProtoServiceFunction( PSS_SETAPPARENTMODE, MsnSetApparentMode ); + MSN_CreateProtoServiceFunction( PSS_USERISTYPING, MsnUserIsTyping ); + + if ( MyOptions.UseMSNP11 ) { + MSN_CreateProtoServiceFunction( PSS_GETAWAYMSG, MsnGetAwayMsg ); + MSN_CreateProtoServiceFunction( PS_SETAWAYMSG, MsnSetAwayMsg ); + } + + MSN_CreateProtoServiceFunction( MSN_SET_AVATAR, MsnSetAvatar ); + MSN_CreateProtoServiceFunction( MSN_SET_NICKNAME, MsnSetNickName ); + MSN_CreateProtoServiceFunction( MSN_SEND_NUDGE, MsnSendNudge ); + return 0; +} + +void UnloadMsnServices( void ) +{ + if ( hHookSettingChanged ) + UnhookEvent( hHookSettingChanged ); + + if ( hHookContactDeleted ) + UnhookEvent( hHookContactDeleted ); + + if ( hHookRebuildCMenu ) + UnhookEvent( hHookRebuildCMenu ); +} -- cgit v1.2.3