diff options
Diffstat (limited to 'protocols/MSN/src/msn_proto.cpp')
| -rw-r--r-- | protocols/MSN/src/msn_proto.cpp | 1107 | 
1 files changed, 0 insertions, 1107 deletions
diff --git a/protocols/MSN/src/msn_proto.cpp b/protocols/MSN/src/msn_proto.cpp deleted file mode 100644 index f289313ee6..0000000000 --- a/protocols/MSN/src/msn_proto.cpp +++ /dev/null @@ -1,1107 +0,0 @@ -/*
 -Plugin of Miranda IM for communicating with users of the MSN Messenger protocol.
 -
 -Copyright (c) 2012-2014 Miranda NG Team
 -Copyright (c) 2008-2012 Boris Krasnovskiy.
 -
 -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, see <http://www.gnu.org/licenses/>.
 -*/
 -
 -#include "msn_global.h"
 -#include "msn_proto.h"
 -
 -static const COLORREF crCols[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
 -
 -int msn_httpGatewayInit(HANDLE hConn,NETLIBOPENCONNECTION *nloc,NETLIBHTTPREQUEST *nlhr);
 -int msn_httpGatewayBegin(HANDLE hConn,NETLIBOPENCONNECTION *nloc);
 -int msn_httpGatewayWrapSend(HANDLE hConn,PBYTE buf,int len,int flags,MIRANDASERVICE pfnNetlibSend);
 -PBYTE msn_httpGatewayUnwrapRecv(NETLIBHTTPREQUEST *nlhr,PBYTE buf,int len,int *outBufLen,void *(*NetlibRealloc)(void*,size_t));
 -
 -static int CompareLists(const MsnContact* p1, const MsnContact* p2)
 -{
 -	return _stricmp(p1->email, p2->email);
 -}
 -
 -CMsnProto::CMsnProto(const char* aProtoName, const TCHAR* aUserName) :
 -	PROTO<CMsnProto>(aProtoName, aUserName),
 -	contList(10, CompareLists),
 -	grpList(10, CompareId),
 -	sttThreads(10, PtrKeySortT),
 -	sessionList(10, PtrKeySortT),
 -	dcList(10, PtrKeySortT),
 -	lsMessageQueue(1),
 -	lsAvatarQueue(1),
 -	msgCache(5, CompareId)
 -{
 -	db_set_resident(m_szModuleName, "Status");
 -	db_set_resident(m_szModuleName, "IdleTS");
 -	db_set_resident(m_szModuleName, "p2pMsgId");
 -	db_set_resident(m_szModuleName, "MobileEnabled");
 -	db_set_resident(m_szModuleName, "MobileAllowed");
 -
 -	// Protocol services and events...
 -	hMSNNudge = CreateProtoEvent("/Nudge");
 -
 -	CreateProtoService(PS_CREATEACCMGRUI, &CMsnProto::SvcCreateAccMgrUI);
 -
 -	CreateProtoService(PS_GETAVATARINFOT, &CMsnProto::GetAvatarInfo);
 -	CreateProtoService(PS_GETMYAWAYMSG, &CMsnProto::GetMyAwayMsg);
 -
 -	CreateProtoService(PS_LEAVECHAT, &CMsnProto::OnLeaveChat);
 -
 -	CreateProtoService(PS_GETMYAVATART, &CMsnProto::GetAvatar);
 -	CreateProtoService(PS_SETMYAVATART, &CMsnProto::SetAvatar);
 -	CreateProtoService(PS_GETAVATARCAPS, &CMsnProto::GetAvatarCaps);
 -
 -	CreateProtoService(PS_GET_LISTENINGTO, &CMsnProto::GetCurrentMedia);
 -	CreateProtoService(PS_SET_LISTENINGTO, &CMsnProto::SetCurrentMedia);
 -
 -	CreateProtoService(PS_SETMYNICKNAME, &CMsnProto::SetNickName);
 -	CreateProtoService(PS_SEND_NUDGE, &CMsnProto::SendNudge);
 -
 -	CreateProtoService(PS_GETUNREADEMAILCOUNT, &CMsnProto::GetUnreadEmailCount);
 -
 -	// event hooks
 -	HookProtoEvent(ME_MSG_WINDOWPOPUP, &CMsnProto::OnWindowPopup);
 -	HookProtoEvent(ME_CLIST_GROUPCHANGE, &CMsnProto::OnGroupChange);
 -	HookProtoEvent(ME_OPT_INITIALISE, &CMsnProto::OnOptionsInit);
 -	HookProtoEvent(ME_CLIST_DOUBLECLICKED, &CMsnProto::OnContactDoubleClicked);
 -
 -	LoadOptions();
 -
 -	for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
 -		delSetting(hContact, "Status");
 -		delSetting(hContact, "IdleTS");
 -		delSetting(hContact, "p2pMsgId");
 -		delSetting(hContact, "AccList");
 -	}
 -	delSetting("MobileEnabled");
 -	delSetting("MobileAllowed");
 -
 -	char path[MAX_PATH];
 -	if (db_get_static(NULL, m_szModuleName, "LoginServer", path, sizeof(path)) == 0 &&
 -		(strcmp(path, MSN_DEFAULT_LOGIN_SERVER) == 0 ||
 -		strcmp(path, MSN_DEFAULT_GATEWAY) == 0))
 -		delSetting("LoginServer");
 -
 -	if (MyOptions.SlowSend) {
 -		if (db_get_dw(NULL, "SRMsg", "MessageTimeout", 10000) < 60000)
 -			db_set_dw(NULL, "SRMsg", "MessageTimeout", 60000);
 -		if (db_get_dw(NULL, "SRMM", "MessageTimeout", 10000) < 60000)
 -			db_set_dw(NULL, "SRMM", "MessageTimeout", 60000);
 -	}
 -
 -	mailsoundname = (char*)mir_alloc(64);
 -	mir_snprintf(mailsoundname, 64, "%s:Hotmail", m_szModuleName);
 -	SkinAddNewSoundExT(mailsoundname, m_tszUserName, LPGENT("Live Mail"));
 -
 -	alertsoundname = (char*)mir_alloc(64);
 -	mir_snprintf(alertsoundname, 64, "%s:Alerts", m_szModuleName);
 -	SkinAddNewSoundExT(alertsoundname, m_tszUserName, LPGENT("Live Alert"));
 -
 -	MsgQueue_Init();
 -	AvatarQueue_Init();
 -	InitCustomFolders();
 -
 -	TCHAR szBuffer[MAX_PATH];
 -	char  szDbsettings[64];
 -
 -	NETLIBUSER nlu1 = { 0 };
 -	nlu1.cbSize = sizeof(nlu1);
 -	nlu1.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_TCHAR;
 -	nlu1.szSettingsModule = szDbsettings;
 -	nlu1.ptszDescriptiveName = szBuffer;
 -
 -	mir_snprintf(szDbsettings, sizeof(szDbsettings), "%s_HTTPS", m_szModuleName);
 -	mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s plugin HTTPS connections"), m_tszUserName);
 -	hNetlibUserHttps = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu1);
 -
 -	NETLIBUSER nlu = { 0 };
 -	nlu.cbSize = sizeof(nlu);
 -	nlu.flags = NUF_INCOMING | NUF_OUTGOING | NUF_HTTPCONNS | NUF_TCHAR;
 -	nlu.szSettingsModule = m_szModuleName;
 -	nlu.ptszDescriptiveName = szBuffer;
 -
 -	nlu.szHttpGatewayUserAgent = (char*)MSN_USER_AGENT;
 -	nlu.pfnHttpGatewayInit = msn_httpGatewayInit;
 -	nlu.pfnHttpGatewayWrapSend = msn_httpGatewayWrapSend;
 -	nlu.pfnHttpGatewayUnwrapRecv = msn_httpGatewayUnwrapRecv;
 -
 -	mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s plugin connections"), m_tszUserName);
 -	m_hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
 -}
 -
 -CMsnProto::~CMsnProto()
 -{
 -	MsnRemoveMainMenus();
 -
 -	DestroyHookableEvent(hMSNNudge);
 -
 -	MSN_FreeGroups();
 -	Threads_Uninit();
 -	MsgQueue_Uninit();
 -	AvatarQueue_Uninit();
 -	Lists_Uninit();
 -	P2pSessions_Uninit();
 -	CachedMsg_Uninit();
 -
 -	Netlib_CloseHandle(m_hNetlibUser);
 -	Netlib_CloseHandle(hNetlibUserHttps);
 -
 -	mir_free(mailsoundname);
 -	mir_free(alertsoundname);
 -
 -	for (int i = 0; i < MSN_NUM_MODES; i++)
 -		mir_free(msnModeMsgs[i]);
 -
 -	mir_free(msnLastStatusMsg);
 -	mir_free(msnPreviousUUX);
 -	mir_free(msnExternalIP);
 -
 -	mir_free(abCacheKey);
 -	mir_free(sharingCacheKey);
 -	mir_free(storageCacheKey);
 -
 -	FreeAuthTokens();
 -}
 -
 -int CMsnProto::OnModulesLoaded(WPARAM, LPARAM)
 -{
 -	GCREGISTER gcr = { 0 };
 -	gcr.cbSize = sizeof(GCREGISTER);
 -	gcr.dwFlags = GC_TYPNOTIF | GC_CHANMGR;
 -	gcr.iMaxText = 0;
 -	gcr.nColors = 16;
 -	gcr.pColors = (COLORREF*)crCols;
 -	gcr.ptszDispName = m_tszUserName;
 -	gcr.pszModule = m_szModuleName;
 -	CallServiceSync(MS_GC_REGISTER, 0, (LPARAM)&gcr);
 -
 -	HookProtoEvent(ME_GC_EVENT, &CMsnProto::MSN_GCEventHook);
 -	HookProtoEvent(ME_GC_BUILDMENU, &CMsnProto::MSN_GCMenuHook);
 -
 -	HookProtoEvent(ME_IDLE_CHANGED, &CMsnProto::OnIdleChanged);
 -	InitPopups();
 -	return 0;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// OnPreShutdown - prepare a global Miranda shutdown
 -
 -int CMsnProto::OnPreShutdown(WPARAM, LPARAM)
 -{
 -	SetEvent(hevAvatarQueue);
 -
 -	Popup_UnregisterClass(hPopupError);
 -	Popup_UnregisterClass(hPopupHotmail);
 -	Popup_UnregisterClass(hPopupNotify);
 -	return 0;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnAddToList - adds contact to the server list
 -
 -MCONTACT CMsnProto::AddToListByEmail(const char *email, const char *nick, DWORD flags)
 -{
 -	MCONTACT hContact = MSN_HContactFromEmail(email, nick, true, flags & PALF_TEMPORARY);
 -
 -	if (flags & PALF_TEMPORARY) {
 -		if (db_get_b(hContact, "CList", "NotOnList", 0) == 1)
 -			db_set_b(hContact, "CList", "Hidden", 1);
 -	}
 -	else {
 -		db_unset(hContact, "CList", "Hidden");
 -		if (msnLoggedIn) {
 -			int netId = strncmp(email, "tel:", 4) ? NETID_MSN : NETID_MOB;
 -			if (MSN_AddUser(hContact, email, netId, LIST_FL)) {
 -				MSN_AddUser(hContact, email, netId, LIST_PL + LIST_REMOVE);
 -				MSN_AddUser(hContact, email, netId, LIST_BL + LIST_REMOVE);
 -				MSN_AddUser(hContact, email, netId, LIST_AL);
 -				db_unset(hContact, "CList", "Hidden");
 -			}
 -			MSN_SetContactDb(hContact, email);
 -
 -			if (MSN_IsMeByContact(hContact)) displayEmailCount(hContact);
 -		}
 -		else hContact = NULL;
 -	}
 -	return hContact;
 -}
 -
 -MCONTACT __cdecl CMsnProto::AddToList(int flags, PROTOSEARCHRESULT* psr)
 -{
 -	TCHAR *id = psr->id ? psr->id : psr->email;
 -	return AddToListByEmail(
 -		psr->flags & PSR_UNICODE ? UTF8((wchar_t*)id) : UTF8((char*)id),
 -		psr->flags & PSR_UNICODE ? UTF8((wchar_t*)psr->nick) : UTF8((char*)psr->nick),
 -		flags);
 -}
 -
 -MCONTACT __cdecl CMsnProto::AddToListByEvent(int flags, int iContact, HANDLE hDbEvent)
 -{
 -	DBEVENTINFO dbei = { sizeof(dbei) };
 -	if ((dbei.cbBlob = db_event_getBlobSize(hDbEvent)) == (DWORD)(-1))
 -		return NULL;
 -
 -	dbei.pBlob = (PBYTE)alloca(dbei.cbBlob);
 -	if (db_event_get(hDbEvent, &dbei)) return NULL;
 -	if (strcmp(dbei.szModule, m_szModuleName)) return NULL;
 -	if (dbei.eventType != EVENTTYPE_AUTHREQUEST) return NULL;
 -
 -	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;
 -
 -	return AddToListByEmail(email, nick, flags);
 -}
 -
 -int CMsnProto::AuthRecv(MCONTACT hContact, PROTORECVEVENT* pre)
 -{
 -	Proto_AuthRecv(m_szModuleName, pre);
 -	return 0;
 -}
 -
 -////////////////////////////////////////////////////////////////////////////////////////
 -// PSS_AUTHREQUEST
 -
 -int __cdecl CMsnProto::AuthRequest(MCONTACT hContact, const TCHAR* szMessage)
 -{
 -	if (msnLoggedIn) {
 -		char email[MSN_MAX_EMAIL_LEN];
 -		if (db_get_static(hContact, m_szModuleName, "e-mail", email, sizeof(email)))
 -			return 1;
 -
 -		char* szMsg = mir_utf8encodeT(szMessage);
 -
 -		int netId = strncmp(email, "tel:", 4) == 0 ? NETID_MOB : NETID_MSN;
 -		if (MSN_AddUser(hContact, email, netId, LIST_FL, szMsg)) {
 -			MSN_AddUser(hContact, email, netId, LIST_PL + LIST_REMOVE);
 -			MSN_AddUser(hContact, email, netId, LIST_BL + LIST_REMOVE);
 -			MSN_AddUser(hContact, email, netId, LIST_AL);
 -		}
 -		MSN_SetContactDb(hContact, email);
 -		mir_free(szMsg);
 -
 -		if (MSN_IsMeByContact(hContact)) displayEmailCount(hContact);
 -		return 0;
 -	}
 -	return 1;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnAuthAllow - called after successful authorization
 -
 -int CMsnProto::Authorize(HANDLE hDbEvent)
 -{
 -	if (!msnLoggedIn)
 -		return 1;
 -
 -	DBEVENTINFO dbei = { sizeof(dbei) };
 -	if ((dbei.cbBlob = db_event_getBlobSize(hDbEvent)) == -1)
 -		return 1;
 -
 -	dbei.pBlob = (PBYTE)alloca(dbei.cbBlob);
 -	if (db_event_get(hDbEvent, &dbei))
 -		return 1;
 -
 -	if (dbei.eventType != EVENTTYPE_AUTHREQUEST)
 -		return 1;
 -
 -	if (strcmp(dbei.szModule, m_szModuleName))
 -		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;
 -
 -	MCONTACT hContact = MSN_HContactFromEmail(email, nick, true, 0);
 -	int netId = Lists_GetNetId(email);
 -
 -	MSN_AddUser(hContact, email, netId, LIST_AL);
 -	MSN_AddUser(hContact, email, netId, LIST_BL + LIST_REMOVE);
 -	MSN_AddUser(hContact, email, netId, LIST_PL + LIST_REMOVE);
 -
 -	MSN_SetContactDb(hContact, email);
 -	return 0;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnAuthDeny - called after unsuccessful authorization
 -
 -int CMsnProto::AuthDeny(HANDLE hDbEvent, const TCHAR* szReason)
 -{
 -	if (!msnLoggedIn)
 -		return 1;
 -
 -	DBEVENTINFO dbei = { sizeof(dbei) };
 -	if ((dbei.cbBlob = db_event_getBlobSize(hDbEvent)) == -1)
 -		return 1;
 -
 -	dbei.pBlob = (PBYTE)alloca(dbei.cbBlob);
 -	if (db_event_get(hDbEvent, &dbei))
 -		return 1;
 -
 -	if (dbei.eventType != EVENTTYPE_AUTHREQUEST)
 -		return 1;
 -
 -	if (strcmp(dbei.szModule, m_szModuleName))
 -		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;
 -
 -	MsnContact* msc = Lists_Get(email);
 -	if (msc == NULL) return 0;
 -
 -	MSN_AddUser(NULL, email, msc->netId, LIST_PL + LIST_REMOVE);
 -	MSN_AddUser(NULL, email, msc->netId, LIST_BL);
 -	MSN_AddUser(NULL, email, msc->netId, LIST_RL);
 -
 -	if (!(msc->list & (LIST_FL | LIST_LL))) {
 -		if (msc->hContact) CallService(MS_DB_CONTACT_DELETE, (WPARAM)msc->hContact, 0);
 -		msc->hContact = NULL;
 -		MCONTACT hContact = MSN_HContactFromEmail(email);
 -		if (hContact) CallService(MS_DB_CONTACT_DELETE, hContact, 0);
 -	}
 -
 -	return 0;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnBasicSearch - search contacts by e-mail
 -
 -void __cdecl CMsnProto::MsnSearchAckThread(void* arg)
 -{
 -	const TCHAR* emailT = (TCHAR*)arg;
 -	char *email = mir_utf8encodeT(emailT);
 -
 -	if (Lists_IsInList(LIST_FL, email)) {
 -		MSN_ShowPopup(emailT, TranslateT("Contact already in your contact list"), MSN_ALLOW_MSGBOX, NULL);
 -		ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, arg, 0);
 -		mir_free(arg);
 -		return;
 -	}
 -
 -	unsigned res = MSN_ABContactAdd(email, NULL, NETID_MSN, NULL, 1, true);
 -	switch (res) {
 -	case 0:
 -	case 2:
 -	case 3:
 -		{
 -			PROTOSEARCHRESULT isr = { 0 };
 -			isr.cbSize = sizeof(isr);
 -			isr.flags = PSR_TCHAR;
 -			isr.id = (TCHAR*)emailT;
 -			isr.nick = (TCHAR*)emailT;
 -			isr.email = (TCHAR*)emailT;
 -
 -			ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, arg, (LPARAM)&isr);
 -			ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, arg, 0);
 -		}
 -		break;
 -
 -	case 1:
 -		if (strstr(email, "@yahoo.com") == NULL)
 -			ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, arg, 0);
 -		else {
 -			msnSearchId = arg;
 -			MSN_FindYahooUser(email);
 -		}
 -		break;
 -
 -	default:
 -		ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, arg, 0);
 -		break;
 -	}
 -	mir_free(email);
 -	mir_free(arg);
 -}
 -
 -
 -HANDLE __cdecl CMsnProto::SearchBasic(const PROTOCHAR* id)
 -{
 -	if (!msnLoggedIn) return 0;
 -
 -	TCHAR* email = mir_tstrdup(id);
 -	ForkThread(&CMsnProto::MsnSearchAckThread, email);
 -
 -	return email;
 -}
 -
 -HANDLE __cdecl CMsnProto::SearchByEmail(const PROTOCHAR* email)
 -{
 -	return SearchBasic(email);
 -}
 -
 -
 -HANDLE __cdecl CMsnProto::SearchByName(const PROTOCHAR* nick, const PROTOCHAR* firstName, const PROTOCHAR* lastName)
 -{
 -	return NULL;
 -}
 -
 -HWND __cdecl CMsnProto::SearchAdvanced(HWND hwndDlg)
 -{
 -	return NULL;
 -}
 -
 -HWND __cdecl CMsnProto::CreateExtendedSearchUI(HWND parent)
 -{
 -	return NULL;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnFileAllow - starts the file transfer
 -
 -void __cdecl CMsnProto::MsnFileAckThread(void* arg)
 -{
 -	filetransfer* ft = (filetransfer*)arg;
 -
 -	TCHAR filefull[MAX_PATH];
 -	mir_sntprintf(filefull, SIZEOF(filefull), _T("%s\\%s"), ft->std.tszWorkingDir, ft->std.tszCurrentFile);
 -	replaceStrT(ft->std.tszCurrentFile, filefull);
 -
 -	if (ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_FILERESUME, ft, (LPARAM)&ft->std))
 -		return;
 -
 -	bool fcrt = ft->create() != -1;
 -
 -	if (ft->p2p_appID != 0) {
 -		if (fcrt)
 -			p2p_sendFeedStart(ft);
 -		p2p_sendStatus(ft, fcrt ? 200 : 603);
 -	}
 -	else msnftp_sendAcceptReject(ft, fcrt);
 -
 -	ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ft, 0);
 -}
 -
 -HANDLE __cdecl CMsnProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* szPath)
 -{
 -	filetransfer* ft = (filetransfer*)hTransfer;
 -
 -	if (!msnLoggedIn || !p2p_sessionRegistered(ft))
 -		return 0;
 -
 -	if ((ft->std.tszWorkingDir = mir_tstrdup(szPath)) == NULL) {
 -		TCHAR szCurrDir[MAX_PATH];
 -		GetCurrentDirectory(SIZEOF(szCurrDir), szCurrDir);
 -		ft->std.tszWorkingDir = mir_tstrdup(szCurrDir);
 -	}
 -	else {
 -		size_t len = _tcslen(ft->std.tszWorkingDir) - 1;
 -		if (ft->std.tszWorkingDir[len] == '\\')
 -			ft->std.tszWorkingDir[len] = 0;
 -	}
 -
 -	ForkThread(&CMsnProto::MsnFileAckThread, ft);
 -
 -	return ft;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnFileCancel - cancels the active file transfer
 -
 -int __cdecl CMsnProto::FileCancel(MCONTACT hContact, HANDLE hTransfer)
 -{
 -	filetransfer* ft = (filetransfer*)hTransfer;
 -
 -	if (!msnLoggedIn || !p2p_sessionRegistered(ft))
 -		return 0;
 -
 -	if (!(ft->std.flags & PFTS_SENDING) && ft->fileId == -1) {
 -		if (ft->p2p_appID != 0)
 -			p2p_sendStatus(ft, 603);
 -		else
 -			msnftp_sendAcceptReject(ft, false);
 -	}
 -	else {
 -		ft->bCanceled = true;
 -		if (ft->p2p_appID != 0) {
 -			p2p_sendCancel(ft);
 -			if (!(ft->std.flags & PFTS_SENDING) && ft->p2p_isV2)
 -				p2p_sessionComplete(ft);
 -		}
 -	}
 -
 -	ft->std.ptszFiles = NULL;
 -	ft->std.totalFiles = 0;
 -	return 0;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnFileDeny - rejects the file transfer request
 -
 -int __cdecl CMsnProto::FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR* /*szReason*/)
 -{
 -	filetransfer* ft = (filetransfer*)hTransfer;
 -
 -	if (!msnLoggedIn || !p2p_sessionRegistered(ft))
 -		return 1;
 -
 -	if (!(ft->std.flags & PFTS_SENDING) && ft->fileId == -1) {
 -		if (ft->p2p_appID != 0)
 -			p2p_sendStatus(ft, 603);
 -		else
 -			msnftp_sendAcceptReject(ft, false);
 -	}
 -	else {
 -		ft->bCanceled = true;
 -		if (ft->p2p_appID != 0)
 -			p2p_sendCancel(ft);
 -	}
 -
 -	return 0;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnFileResume - renames a file
 -
 -int __cdecl CMsnProto::FileResume(HANDLE hTransfer, int* action, const PROTOCHAR** szFilename)
 -{
 -	filetransfer* ft = (filetransfer*)hTransfer;
 -
 -	if (!msnLoggedIn || !p2p_sessionRegistered(ft))
 -		return 1;
 -
 -	switch (*action) {
 -	case FILERESUME_SKIP:
 -		if (ft->p2p_appID != 0)
 -			p2p_sendStatus(ft, 603);
 -		else
 -			msnftp_sendAcceptReject(ft, false);
 -		break;
 -
 -	case FILERESUME_RENAME:
 -		replaceStrT(ft->std.tszCurrentFile, *szFilename);
 -
 -	default:
 -		bool fcrt = ft->create() != -1;
 -		if (ft->p2p_appID != 0) {
 -			if (fcrt)
 -				p2p_sendFeedStart(ft);
 -
 -			p2p_sendStatus(ft, fcrt ? 200 : 603);
 -		}
 -		else
 -			msnftp_sendAcceptReject(ft, fcrt);
 -
 -		ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ft, 0);
 -		break;
 -	}
 -
 -	return 0;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnGetAwayMsg - reads the current status message for a user
 -
 -typedef struct AwayMsgInfo_tag
 -{
 -	INT_PTR id;
 -	MCONTACT hContact;
 -} AwayMsgInfo;
 -
 -void __cdecl CMsnProto::MsnGetAwayMsgThread(void* arg)
 -{
 -	Sleep(150);
 -
 -	AwayMsgInfo *inf = (AwayMsgInfo*)arg;
 -	DBVARIANT dbv;
 -	if (!db_get_ts(inf->hContact, "CList", "StatusMsg", &dbv)) {
 -		ProtoBroadcastAck(inf->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)inf->id, (LPARAM)dbv.ptszVal);
 -		db_free(&dbv);
 -	}
 -	else ProtoBroadcastAck(inf->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)inf->id, 0);
 -
 -	mir_free(inf);
 -}
 -
 -HANDLE __cdecl CMsnProto::GetAwayMsg(MCONTACT hContact)
 -{
 -	AwayMsgInfo* inf = (AwayMsgInfo*)mir_alloc(sizeof(AwayMsgInfo));
 -	inf->hContact = hContact;
 -	inf->id = MSN_GenRandom();
 -
 -	ForkThread(&CMsnProto::MsnGetAwayMsgThread, inf);
 -	return (HANDLE)inf->id;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnGetCaps - obtain the protocol capabilities
 -
 -DWORD_PTR __cdecl CMsnProto::GetCaps(int type, MCONTACT hContact)
 -{
 -	switch (type) {
 -	case PFLAGNUM_1:
 -		return PF1_IM | PF1_SERVERCLIST | PF1_AUTHREQ | PF1_BASICSEARCH |
 -			PF1_ADDSEARCHRES | PF1_CHAT |
 -			PF1_FILESEND | PF1_FILERECV | PF1_URLRECV | PF1_VISLIST | PF1_MODEMSG;
 -
 -	case PFLAGNUM_2:
 -		return PF2_ONLINE | PF2_SHORTAWAY | PF2_LIGHTDND | PF2_INVISIBLE | PF2_ONTHEPHONE | PF2_IDLE;
 -
 -	case PFLAGNUM_3:
 -		return PF2_ONLINE | PF2_SHORTAWAY | PF2_LIGHTDND;
 -
 -	case PFLAGNUM_4:
 -		return PF4_FORCEAUTH | PF4_FORCEADDED | PF4_SUPPORTTYPING | PF4_AVATARS | PF4_SUPPORTIDLE | PF4_IMSENDUTF |
 -			PF4_IMSENDOFFLINE | PF4_NOAUTHDENYREASON;
 -
 -	case PFLAGNUM_5:
 -		return PF2_ONTHEPHONE;
 -
 -	case PFLAG_UNIQUEIDTEXT:
 -		return (UINT_PTR)Translate("Live ID");
 -
 -	case PFLAG_UNIQUEIDSETTING:
 -		return (UINT_PTR)"e-mail";
 -
 -	case PFLAG_MAXLENOFMESSAGE:
 -		return 1202;
 -	}
 -
 -	return 0;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnGetInfo - nothing to do, cause we cannot obtain information from the server
 -
 -int __cdecl CMsnProto::GetInfo(MCONTACT hContact, int infoType)
 -{
 -	return 1;
 -}
 -
 -////////////////////////////////////////////////////////////////////////////////////////
 -// RecvContacts
 -
 -int __cdecl CMsnProto::RecvContacts(MCONTACT hContact, PROTORECVEVENT*)
 -{
 -	return 1;
 -}
 -
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnRecvFile - creates a database event from the file request been received
 -
 -int __cdecl CMsnProto::RecvFile(MCONTACT hContact, PROTOFILEEVENT* evt)
 -{
 -	return Proto_RecvFile(hContact, evt);
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnRecvMessage - creates a database event from the message been received
 -
 -int __cdecl CMsnProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT* pre)
 -{
 -	char tEmail[MSN_MAX_EMAIL_LEN];
 -	db_get_static(hContact, m_szModuleName, "e-mail", tEmail, sizeof(tEmail));
 -
 -	if (Lists_IsInList(LIST_FL, tEmail))
 -		db_unset(hContact, "CList", "Hidden");
 -
 -	return Proto_RecvMessage(hContact, pre);
 -}
 -
 -////////////////////////////////////////////////////////////////////////////////////////
 -// RecvUrl
 -
 -int __cdecl CMsnProto::RecvUrl(MCONTACT hContact, PROTORECVEVENT*)
 -{
 -	return 1;
 -}
 -
 -////////////////////////////////////////////////////////////////////////////////////////
 -// SendContacts
 -
 -int __cdecl CMsnProto::SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT *hContactsList)
 -{
 -	return 1;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnSendFile - initiates a file transfer
 -
 -HANDLE __cdecl CMsnProto::SendFile(MCONTACT hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles)
 -{
 -	if (!msnLoggedIn)
 -		return 0;
 -
 -	if (getWord(hContact, "Status", ID_STATUS_OFFLINE) == ID_STATUS_OFFLINE)
 -		return 0;
 -
 -	MsnContact *cont = Lists_Get(hContact);
 -
 -	if (!cont || _stricmp(cont->email, MyOptions.szEmail) == 0) return 0;
 -
 -	if ((cont->cap1 & 0xf0000000) == 0 && cont->netId != NETID_MSN) return 0;
 -
 -	filetransfer* sft = new filetransfer(this);
 -	sft->std.ptszFiles = ppszFiles;
 -	sft->std.hContact = hContact;
 -	sft->std.flags |= PFTS_SENDING;
 -
 -	int count = 0;
 -	while (ppszFiles[count] != NULL) {
 -		struct _stati64 statbuf;
 -		if (_tstati64(ppszFiles[count++], &statbuf) == 0 && (statbuf.st_mode & _S_IFDIR) == 0) {
 -			sft->std.totalBytes += statbuf.st_size;
 -			++sft->std.totalFiles;
 -		}
 -	}
 -
 -	if (sft->openNext() == -1) {
 -		delete sft;
 -		return 0;
 -	}
 -
 -	if (cont->cap1 & 0xf0000000)
 -		p2p_invite(MSN_APPID_FILE, sft, NULL);
 -	else {
 -		sft->p2p_dest = mir_strdup(cont->email);
 -		msnftp_invite(sft);
 -	}
 -
 -	ProtoBroadcastAck(hContact, ACKTYPE_FILE, ACKRESULT_SENTREQUEST, sft, 0);
 -	return sft;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnSendMessage - sends the message to a server
 -
 -struct TFakeAckParams
 -{
 -	inline TFakeAckParams(MCONTACT p2, long p3, const char* p4, CMsnProto *p5) :
 -		hContact(p2),
 -		id(p3),
 -		msg(p4),
 -		proto(p5)
 -	{}
 -
 -	MCONTACT hContact;
 -	long	id;
 -	const char*	msg;
 -	CMsnProto *proto;
 -};
 -
 -void CMsnProto::MsnFakeAck(void* arg)
 -{
 -	TFakeAckParams* tParam = (TFakeAckParams*)arg;
 -
 -	Sleep(150);
 -	tParam->proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_MESSAGE,
 -		tParam->msg ? ACKRESULT_FAILED : ACKRESULT_SUCCESS,
 -		(HANDLE)tParam->id, LPARAM(tParam->msg));
 -
 -	delete tParam;
 -}
 -
 -int __cdecl CMsnProto::SendMsg(MCONTACT hContact, int flags, const char* pszSrc)
 -{
 -	const char *errMsg = NULL;
 -
 -	if (!msnLoggedIn) {
 -		errMsg = Translate("Protocol is offline");
 -		ForkThread(&CMsnProto::MsnFakeAck, new TFakeAckParams(hContact, 999999, errMsg, this));
 -		return 999999;
 -	}
 -
 -	char tEmail[MSN_MAX_EMAIL_LEN];
 -	if (MSN_IsMeByContact(hContact, tEmail)) {
 -		errMsg = Translate("You cannot send message to yourself");
 -		ForkThread(&CMsnProto::MsnFakeAck, new TFakeAckParams(hContact, 999999, errMsg, this));
 -		return 999999;
 -	}
 -
 -	char *msg = (char*)pszSrc;
 -	if (msg == NULL) return 0;
 -
 -	if (flags & PREF_UNICODE) {
 -		char* p = strchr(msg, '\0');
 -		if (p != msg) {
 -			while (*(++p) == '\0') {}
 -			msg = mir_utf8encodeW((wchar_t*)p);
 -		}
 -		else
 -			msg = mir_strdup(msg);
 -	}
 -	else
 -		msg = (flags & PREF_UTF) ? mir_strdup(msg) : mir_utf8encode(msg);
 -
 -	int rtlFlag = (flags & PREF_RTL) ? MSG_RTL : 0;
 -
 -	int seq = 0;
 -	int netId = Lists_GetNetId(tEmail);
 -
 -	switch (netId) {
 -	case NETID_MOB:
 -		if (strlen(msg) > 133) {
 -			errMsg = Translate("Message is too long: SMS page limited to 133 UTF8 chars");
 -			seq = 999997;
 -		}
 -		else {
 -			errMsg = NULL;
 -			seq = msnNsThread->sendMessage('1', tEmail, netId, msg, rtlFlag);
 -		}
 -		ForkThread(&CMsnProto::MsnFakeAck, new TFakeAckParams(hContact, seq, errMsg, this));
 -		break;
 -
 -	case NETID_YAHOO:
 -		if (strlen(msg) > 1202) {
 -			seq = 999996;
 -			errMsg = Translate("Message is too long: MSN messages are limited by 1202 UTF8 chars");
 -			ForkThread(&CMsnProto::MsnFakeAck, new TFakeAckParams(hContact, seq, errMsg, this));
 -		}
 -		else {
 -			seq = msnNsThread->sendMessage('1', tEmail, netId, msg, rtlFlag);
 -			ForkThread(&CMsnProto::MsnFakeAck, new TFakeAckParams(hContact, seq, NULL, this));
 -		}
 -		break;
 -
 -	default:
 -		if (strlen(msg) > 1202) {
 -			seq = 999996;
 -			errMsg = Translate("Message is too long: MSN messages are limited by 1202 UTF8 chars");
 -			ForkThread(&CMsnProto::MsnFakeAck, new TFakeAckParams(hContact, seq, errMsg, this));
 -		}
 -		else {
 -			const char msgType = MyOptions.SlowSend ? 'A' : 'N';
 -			bool isOffline;
 -			ThreadData* thread = MSN_StartSB(tEmail, isOffline);
 -			if (thread == NULL) {
 -				if (isOffline) {
 -					if (netId != NETID_LCS) {
 -						seq = msnNsThread->sendMessage('1', tEmail, netId, msg, rtlFlag | MSG_OFFLINE);
 -						ForkThread(&CMsnProto::MsnFakeAck, new TFakeAckParams(hContact, seq, NULL, this));
 -					}
 -					else {
 -						seq = 999993;
 -						errMsg = Translate("Offline messaging is not allowed for LCS contacts");
 -						ForkThread(&CMsnProto::MsnFakeAck, new TFakeAckParams(hContact, seq, errMsg, this));
 -					}
 -				}
 -				else
 -					seq = MsgQueue_Add(tEmail, msgType, msg, 0, 0, rtlFlag);
 -			}
 -			else {
 -				seq = thread->sendMessage(msgType, tEmail, netId, msg, rtlFlag);
 -				if (!MyOptions.SlowSend)
 -					ForkThread(&CMsnProto::MsnFakeAck, new TFakeAckParams(hContact, seq, NULL, this));
 -			}
 -		}
 -		break;
 -	}
 -
 -	mir_free(msg);
 -	return seq;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnSetAwayMsg - sets the current status message for a user
 -
 -int __cdecl CMsnProto::SetAwayMsg(int status, const TCHAR* msg)
 -{
 -	char** msgptr = GetStatusMsgLoc(status);
 -
 -	if (msgptr == NULL)
 -		return 1;
 -
 -	mir_free(*msgptr);
 -	char* buf = *msgptr = mir_utf8encodeT(msg);
 -	if (buf && strlen(buf) > 1859) {
 -		buf[1859] = 0;
 -		const int i = 1858;
 -		if (buf[i] & 128) {
 -			if (buf[i] & 64)
 -				buf[i] = '\0';
 -			else if ((buf[i - 1] & 224) == 224)
 -				buf[i - 1] = '\0';
 -			else if ((buf[i - 2] & 240) == 240)
 -				buf[i - 2] = '\0';
 -		}
 -	}
 -
 -	if (status == m_iDesiredStatus)
 -		MSN_SendStatusMessage(*msgptr);
 -
 -	return 0;
 -}
 -
 -////////////////////////////////////////////////////////////////////////////////////////
 -// PSR_AWAYMSG
 -
 -int __cdecl CMsnProto::RecvAwayMsg(MCONTACT hContact, int statusMode, PROTORECVEVENT* evt)
 -{
 -	return 1;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnSetStatus - set the plugin's connection status
 -
 -int __cdecl CMsnProto::SetStatus(int iNewStatus)
 -{
 -	if (m_iDesiredStatus == iNewStatus) return 0;
 -
 -	m_iDesiredStatus = iNewStatus;
 -	debugLogA("PS_SETSTATUS(%d,0)", iNewStatus);
 -
 -	if (m_iDesiredStatus == ID_STATUS_OFFLINE) {
 -		if (msnNsThread)
 -			msnNsThread->sendTerminate();
 -	}
 -	else if (!msnLoggedIn && m_iStatus == ID_STATUS_OFFLINE) {
 -		char szPassword[100];
 -		int ps = db_get_static(NULL, m_szModuleName, "Password", szPassword, sizeof(szPassword));
 -		if (ps != 0 || *szPassword == 0) {
 -			ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_WRONGPASSWORD);
 -			m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
 -			return 0;
 -		}
 -
 -		if (*MyOptions.szEmail == 0) {
 -			ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_BADUSERID);
 -			m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
 -			return 0;
 -		}
 -
 -		sessionList.destroy();
 -		dcList.destroy();
 -
 -		usingGateway = false;
 -
 -		int oldMode = m_iStatus;
 -		m_iStatus = ID_STATUS_CONNECTING;
 -		ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldMode, m_iStatus);
 -
 -		ThreadData* newThread = new ThreadData;
 -
 -		newThread->mType = SERVER_NOTIFICATION;
 -		newThread->mIsMainThread = true;
 -
 -		newThread->startThread(&CMsnProto::MSNServerThread, this);
 -	}
 -	else
 -		if (m_iStatus > ID_STATUS_OFFLINE) MSN_SetServerStatus(m_iDesiredStatus);
 -
 -	return 0;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -// MsnUserIsTyping - notify another contact that we're typing a message
 -
 -int __cdecl CMsnProto::UserIsTyping(MCONTACT hContact, int type)
 -{
 -	if (!msnLoggedIn) return 0;
 -
 -	char tEmail[MSN_MAX_EMAIL_LEN];
 -	if (MSN_IsMeByContact(hContact, tEmail)) return 0;
 -
 -	bool typing = type == PROTOTYPE_SELFTYPING_ON;
 -
 -	int netId = Lists_GetNetId(tEmail);
 -	switch (netId) {
 -	case NETID_UNKNOWN:
 -	case NETID_MSN:
 -	case NETID_LCS:
 -		{
 -			bool isOffline;
 -			ThreadData* thread = MSN_StartSB(tEmail, isOffline);
 -
 -			if (thread == NULL) {
 -				if (isOffline) return 0;
 -				MsgQueue_Add(tEmail, 2571, NULL, 0, NULL, typing);
 -			}
 -			else
 -				MSN_StartStopTyping(thread, typing);
 -		}
 -		break;
 -
 -	case NETID_YAHOO:
 -		if (typing) MSN_SendTyping(msnNsThread, tEmail, netId);
 -		break;
 -
 -	default:
 -		break;
 -	}
 -
 -	return 0;
 -}
 -
 -////////////////////////////////////////////////////////////////////////////////////////
 -// SendUrl
 -
 -int __cdecl CMsnProto::SendUrl(MCONTACT hContact, int flags, const char* url)
 -{
 -	return 1;
 -}
 -
 -/////////////////////////////////////////////////////////////////////////////////////////
 -//	MsnSetApparentMode - controls contact visibility
 -
 -int __cdecl CMsnProto::SetApparentMode(MCONTACT hContact, int mode)
 -{
 -	if (mode && mode != ID_STATUS_OFFLINE)
 -		return 1;
 -
 -	WORD oldMode = getWord(hContact, "ApparentMode", 0);
 -	if (mode != oldMode)
 -		setWord(hContact, "ApparentMode", (WORD)mode);
 -
 -	return 1;
 -}
 -
 -int __cdecl CMsnProto::OnEvent(PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam)
 -{
 -	switch (eventType) {
 -	case EV_PROTO_ONLOAD:
 -		return OnModulesLoaded(0, 0);
 -
 -	case EV_PROTO_ONEXIT:
 -		return OnPreShutdown(0, 0);
 -
 -	case EV_PROTO_ONOPTIONS:
 -		return OnOptionsInit(wParam, lParam);
 -
 -	case EV_PROTO_ONMENU:
 -		MsnInitMainMenu();
 -		break;
 -
 -	case EV_PROTO_ONERASE:
 -		{
 -			char szDbsettings[64];
 -			mir_snprintf(szDbsettings, sizeof(szDbsettings), "%s_HTTPS", m_szModuleName);
 -			CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)szDbsettings);
 -		}
 -		break;
 -
 -	case EV_PROTO_ONRENAME:
 -		if (mainMenuRoot) {
 -			CLISTMENUITEM clmi = { sizeof(clmi) };
 -			clmi.flags = CMIM_NAME | CMIF_TCHAR;
 -			clmi.ptszName = m_tszUserName;
 -			Menu_ModifyItem(mainMenuRoot, &clmi);
 -		}
 -		break;
 -
 -	case EV_PROTO_ONCONTACTDELETED:
 -		return OnContactDeleted(wParam, lParam);
 -
 -	case EV_PROTO_DBSETTINGSCHANGED:
 -		return OnDbSettingChanged(wParam, lParam);
 -	}
 -	return 1;
 -}
  | 
