From 7cf93849b55a578640195e58427f33d3254bc562 Mon Sep 17 00:00:00 2001
From: Alexander Lantsev <aunsane@gmail.com>
Date: Tue, 4 Jun 2013 19:29:50 +0000
Subject: Skype: - fixed messaging in chats - fixed incoming transfer status
 (probably fixed #358) - fixed #357

git-svn-id: http://svn.miranda-ng.org/main/trunk@4884 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
---
 protocols/Skype/src/skype.h             |   1 +
 protocols/Skype/src/skype_account.cpp   |   6 +-
 protocols/Skype/src/skype_chat.cpp      | 593 ++++++--------------------------
 protocols/Skype/src/skype_chat.h        |  24 +-
 protocols/Skype/src/skype_contacts.cpp  |   4 +-
 protocols/Skype/src/skype_proto.cpp     |  13 +-
 protocols/Skype/src/skype_proto.h       |  25 +-
 protocols/Skype/src/skype_transfers.cpp |   2 +-
 8 files changed, 130 insertions(+), 538 deletions(-)

(limited to 'protocols/Skype')

diff --git a/protocols/Skype/src/skype.h b/protocols/Skype/src/skype.h
index 27d7fcfed2..fa3261dc38 100644
--- a/protocols/Skype/src/skype.h
+++ b/protocols/Skype/src/skype.h
@@ -15,6 +15,7 @@
 #include <m_clist.h>
 #include <m_clistint.h>
 #include <m_clui.h>
+#include <m_core.h>
 #include <m_database.h>
 #include <m_langpack.h>
 #include <m_message.h>
diff --git a/protocols/Skype/src/skype_account.cpp b/protocols/Skype/src/skype_account.cpp
index 1121628193..bbdb402aad 100644
--- a/protocols/Skype/src/skype_account.cpp
+++ b/protocols/Skype/src/skype_account.cpp
@@ -180,9 +180,8 @@ void CSkypeProto::InitProxy()
 				this->SetStr(SETUPKEY_HTTPS_PROXY_ADDR, address);
 				if (nlus.useProxyAuth)
 				{
-					ptrA encodedPass( mir_base64_encode((BYTE*)nlus.szProxyAuthPassword, lstrlenA(nlus.szProxyAuthPassword)));
-
 					this->SetStr(SETUPKEY_HTTPS_PROXY_USER, nlus.szProxyAuthUser);
+					ptrA encodedPass(::mir_base64_encode((BYTE*)nlus.szProxyAuthPassword, ::lstrlenA(nlus.szProxyAuthPassword)));
 					this->SetStr(SETUPKEY_HTTPS_PROXY_PWD,	(char*)encodedPass);
 				}
 				break;
@@ -196,7 +195,8 @@ void CSkypeProto::InitProxy()
 				if (nlus.useProxyAuth)
 				{
 					this->SetStr(SETUPKEY_SOCKS_PROXY_USER, nlus.szProxyAuthUser);
-					this->SetStr(SETUPKEY_SOCKS_PROXY_PWD,	nlus.szProxyAuthPassword);
+					ptrA encodedPass(::mir_base64_encode((BYTE*)nlus.szProxyAuthPassword, ::lstrlenA(nlus.szProxyAuthPassword)));
+					this->SetStr(SETUPKEY_SOCKS_PROXY_PWD,	(char*)encodedPass);
 				}
 				break;
 
diff --git a/protocols/Skype/src/skype_chat.cpp b/protocols/Skype/src/skype_chat.cpp
index 73839e4f00..311e9ce570 100644
--- a/protocols/Skype/src/skype_chat.cpp
+++ b/protocols/Skype/src/skype_chat.cpp
@@ -36,8 +36,6 @@ void CSkypeProto::InitChat()
 
 	this->HookEvent(ME_GC_EVENT, &CSkypeProto::OnGCEventHook);
 	this->HookEvent(ME_GC_BUILDMENU, &CSkypeProto::OnGCMenuHook);
-
-	this->chatList = new ChatList(this);
 }
 
 ///
@@ -71,7 +69,6 @@ ChatRoom::ChatRoom(const wchar_t *cid, const wchar_t *name, CSkypeProto *ppro) :
 	//
 	this->me = new ChatMember(ppro->login);
 	this->me->nick = ::mir_wstrdup(::TranslateT("me"));
-		//::db_get_wsa(NULL, ppro->m_szModuleName, "Nick");
 }
 
 ChatRoom::~ChatRoom()
@@ -197,11 +194,6 @@ void ChatRoom::SendEvent(const wchar_t *sid, int eventType, DWORD timestamp, DWO
 		this->SendEvent(this->me, eventType, timestamp, flags, itemData, status, message);
 }
 
-void ChatRoom::AppendMessage(const wchar_t *sid, const wchar_t *message, DWORD timestamp, int eventType)
-{
-	//this->SendEvent(sid, eventType, timestamp, GCEF_ADDTOLOG, 0, NULL, message);
-}
-
 bool ChatRoom::IsMe(const wchar_t *sid) const
 {
 	return ::lstrcmpi(this->me->sid, sid) == 0;
@@ -344,7 +336,14 @@ void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &me
 			uint timestamp;
 			message->GetPropTimestamp(timestamp);
 			
-			this->AppendMessage(sid, text, timestamp, messageType == CMessage::POSTED_TEXT ? GC_EVENT_MESSAGE : GC_EVENT_ACTION);
+			this->SendEvent(
+				sid, 
+				messageType == CMessage::POSTED_TEXT ? GC_EVENT_MESSAGE : GC_EVENT_ACTION,
+				timestamp,
+				GCEF_ADDTOLOG,
+				0,
+				NULL,
+				text);
 		}
 		break;
 
@@ -520,185 +519,6 @@ void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &me
 	}
 }
 
-int __cdecl ChatRoom::OnGCEventHook(WPARAM, LPARAM lParam)
-{
-	GCHOOK *gch = (GCHOOK *)lParam;
-	if (!gch) return 1;
-
-	//if (::strcmp(gch->pDest->pszModule, this->m_szModuleName))
-		return 0;
-
-	mir_ptr<wchar_t> cid( ::mir_wstrdup(gch->pDest->ptszID));
-	mir_ptr<wchar_t> sid( ::mir_wstrdup(gch->ptszUID));
-
-	CConversation::Ref conversation;
-	switch (gch->pDest->iType) {
-	case GC_SESSION_TERMINATE:
-		/*if (this->GetConversationByIdentity(::mir_utf8encodeW(cid), conversation, false))
-		{
-			Participant::Refs participants;
-			conversation->GetParticipants(participants, CConversation::MYSELF);
-			participants[0]->Retire();
-		}*/
-		break;
-
-	case GC_USER_MESSAGE:
-		if (gch->ptszText && gch->ptszText[0])
-		{
-			/*if (this->GetConversationByIdentity(::mir_utf8encodeW(cid), conversation, false))
-			{
-				CMessage::Ref message;
-				mir_ptr<char> text(::mir_utf8encodeW(gch->ptszText));
-				conversation->PostText((char *)text, message);
-			}*/
-		}
-		break;
-
-	/*case GC_USER_CHANMGR:
-		if (this->GetConversationByIdentity(::mir_utf8encodeW(cid), conversation, false))
-		{
-			StringList invitedContacts(this->GetChatUsers(cid));
-			this->InviteConactsToChat(conversation, invitedContacts); 
-		}
-		break;*/
-
-	case GC_USER_PRIVMESS:
-		//::CallService(MS_MSG_SENDMESSAGE, (WPARAM)this->GetContactBySid(sid), 0);
-		break;
-
-	case GC_USER_LOGMENU:
-		switch(gch->dwData) {
-		case 10:
-			/*if (this->GetConversationByIdentity(::mir_utf8encodeW(cid), conversation, false))
-			{
-				StringList invitedContacts(this->GetChatUsers(cid));
-				this->InviteConactsToChat(conversation, invitedContacts);
-			}*/
-			break;
-
-		case 20:
-			//this->LeaveChat(cid);
-			break;
-		}
-		break;
-
-	case GC_USER_NICKLISTMENU:
-		switch (gch->dwData) {
-		case 10:
-			//::CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)this->GetContactBySid(sid), 0);
-			break;
-
-		case 20:
-			//CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)this->GetContactBySid(sid), 0);
-			break;
-
-		case 110:
-			//this->LeaveChat(cid);
-			break;
-		}
-		break;
-
-	case GC_USER_TYPNOTIFY:
-		break;
-	}
-	return 0;
-}
-
-int __cdecl ChatRoom::OnGCMenuHook(WPARAM, LPARAM lParam)
-{
-	GCMENUITEMS *gcmi = (GCMENUITEMS*) lParam;
-
-	GC_INFO gci = {0};
-	gci.Flags = BYID | DATA;
-	gci.pszModule = gcmi->pszModule;
-
-	::CallServiceSync(MS_GC_GETINFO, 0, (LPARAM)&gci);
-
-	ChatRoom *room = (ChatRoom *)gci.dwItemData;
-
-	if (room == NULL || ::stricmp(gcmi->pszModule, room->ppro->m_szModuleName))
-		return 0;
-
-	if (gcmi->Type == MENU_ON_LOG)
-	{
-		static const struct gc_item Items[] = 
-		{
-			{ TranslateT("Invite to conference"), 10, MENU_ITEM, FALSE },
-			{ TranslateT("&Leave chat session"), 20, MENU_ITEM, FALSE }
-		};
-		gcmi->nItems = SIZEOF(Items);
-		gcmi->Item = (gc_item*)Items;
-	}
-	else if (gcmi->Type == MENU_ON_NICKLIST)
-	{
-		static const struct gc_item Items[] = 
-		{
-			{ TranslateT("User &details"), 10, MENU_ITEM, FALSE },
-			{ TranslateT("User &history"), 20, MENU_ITEM, FALSE },
-		};
-		gcmi->nItems = SIZEOF(Items);
-		gcmi->Item = (gc_item*)Items;
-	}
-
-	return 0;
-}
-
-///
-
-ChatList::ChatList(CSkypeProto *ppro) : chatRooms(1, CompareChatRooms)
-{
-	this->ppro = ppro;
-}
-
-ChatList::~ChatList()
-{
-	for (int i = 0; this->chatRooms.getCount(); i++)
-		delete this->chatRooms[i];
-	this->chatRooms.destroy();
-}
-
-ChatRoom *ChatList::FindChatRoom(ChatRoom *item)
-{
-	return this->chatRooms.find(item);
-}
-
-ChatRoom *ChatList::FindChatRoom(const wchar_t *cid)
-{
-	ChatRoom search(cid);
-	return this->chatRooms.find(&search);
-}
-
-HANDLE ChatList::AddChatRoom(ChatRoom *item)
-{
-	ChatRoom search(item->cid);
-	ChatRoom *room = this->chatRooms.find(&search);
-	if (room == NULL)
-		room = item;
-
-	this->chatRooms.insert(room);
-
-	HANDLE hContact = ppro->GetChatRoomByCid(room->cid);
-	if ( !hContact)
-	{
-		hContact = (HANDLE)::CallService(MS_DB_CONTACT_ADD, 0, 0);
-		::CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)ppro->m_szModuleName);
-
-		::db_set_b(hContact, ppro->m_szModuleName, "ChatRoom", 1);
-		::db_set_ws(hContact, ppro->m_szModuleName, "ChatRoomID", room->cid);
-		::db_set_ws(hContact, ppro->m_szModuleName, "Nick", room->name);
-		::db_set_w(hContact, ppro->m_szModuleName, "Status", ID_STATUS_OFFLINE);
-		::db_set_w(hContact, ppro->m_szModuleName, "ApparentMode", ID_STATUS_OFFLINE);
-		
-		ptrW defaultGroup = ::db_get_wsa(NULL, "Chat", "AddToGroup");
-		if (defaultGroup != NULL)
-		{
-			::db_set_ws(hContact, "CList", "Group", defaultGroup);
-		}
-	}
-
-	return hContact;
-}
-
 ///
 
 void CSkypeProto::ChatValidateContact(HANDLE hItem, HWND hwndList, const StringList &contacts)
@@ -897,7 +717,7 @@ HANDLE CSkypeProto::AddChatRoom(CConversation::Ref conversation)
 	SEString data;
 
 	conversation->GetPropIdentity(data);
-	mir_ptr<wchar_t> cid = ::mir_utf8decodeW(data);
+	ptrW cid = ::mir_utf8decodeW(data);
 
 	HANDLE hContact = this->GetChatRoomByCid(cid);
 	if ( !hContact)
@@ -906,16 +726,17 @@ HANDLE CSkypeProto::AddChatRoom(CConversation::Ref conversation)
 		::CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)this->m_szModuleName);
 
 		conversation->GetPropDisplayname(data);
-		mir_ptr<wchar_t> name = ::mir_utf8decodeW(data);
+		ptrW name = ::mir_utf8decodeW(data);
 
 		::db_set_b(hContact, this->m_szModuleName, "ChatRoom", 1);
+		::db_set_ws(hContact, this->m_szModuleName, SKYPE_SETTINGS_LOGIN, cid);
 		::db_set_ws(hContact, this->m_szModuleName, "ChatRoomID", cid);
 		::db_set_ws(hContact, this->m_szModuleName, "Nick", name);
 		::db_set_w(hContact, this->m_szModuleName, "Status", ID_STATUS_OFFLINE);
 		::db_set_w(hContact, this->m_szModuleName, "ApparentMode", ID_STATUS_OFFLINE);
 		
-		mir_ptr<wchar_t> defaultGroup = ::db_get_wsa(NULL, "Chat", "AddToGroup");
-		if (defaultGroup)
+		ptrW defaultGroup = ::db_get_wsa(NULL, "Chat", "AddToGroup");
+		if (defaultGroup != NULL)
 		{
 			::db_set_ws(hContact, "CList", "Group", defaultGroup);
 		}
@@ -924,45 +745,7 @@ HANDLE CSkypeProto::AddChatRoom(CConversation::Ref conversation)
 	return hContact;
 }
 
-
-void CSkypeProto::CreateChatWindow(CConversation::Ref conversation, bool showWindow)
-{
-	SEString data;
-
-	conversation->GetPropIdentity(data);
-	mir_ptr<wchar_t> cid( ::mir_utf8decodeW(data));
-
-	conversation->GetPropDisplayname(data);
-	mir_ptr<wchar_t> chatName( ::mir_utf8decodeW(data));
-
-	GCSESSION gcw = {0};
-	gcw.cbSize = sizeof(gcw);
-	gcw.iType = GCW_CHATROOM;
-	gcw.dwFlags = GC_TCHAR;
-	gcw.pszModule = this->m_szModuleName;
-	gcw.ptszName = chatName;
-	gcw.ptszID = cid;
-	::CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcw);
-
-	GCDEST gcd = { m_szModuleName, { NULL }, GC_EVENT_ADDGROUP };
-	gcd.ptszID = cid;
-
-	GCEVENT gce = {0};
-	gce.cbSize = sizeof(GCEVENT);
-	gce.dwFlags = GC_TCHAR;
-	gce.pDest = &gcd;
-	for (int i = 0; i < SIZEOF(CSkypeProto::Roles); i++)
-	{
-		gce.ptszStatus =:: TranslateW(CSkypeProto::Roles[i]);
-		::CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce);
-	}
-
-	gcd.iType = GC_EVENT_CONTROL;
-	::CallServiceSync(MS_GC_EVENT, showWindow ? SESSION_INITDONE : WINDOW_HIDDEN, (LPARAM)&gce);
-	::CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce);
-}
-
-CConversation::Ref CSkypeProto::StartChat(StringList &invitedContacts)
+void CSkypeProto::StartChat(StringList &invitedContacts)
 {
 	InviteChatParam *param = new InviteChatParam(NULL, invitedContacts, this);
 
@@ -985,185 +768,32 @@ CConversation::Ref CSkypeProto::StartChat(StringList &invitedContacts)
 		}
 
 		CConversation::Ref conversation;
-		if (this->CreateConferenceWithConsumers(conversation, needToAdd))
-		{
-			delete param;
-
-			return conversation;
-		}
+		this->CreateConferenceWithConsumers(conversation, needToAdd);
 	}
 
 	delete param;
-
-	return NULL;
 }
 
-CConversation::Ref CSkypeProto::StartChat()
+void CSkypeProto::StartChat()
 {
 	StringList empty;
 	return this->StartChat(empty);
 }
 
-void CSkypeProto::InviteConactsToChat(CConversation::Ref conversation, const StringList &invitedContacts)
-{
-	SEString data;
-
-	conversation->GetPropIdentity(data);
-	mir_ptr<wchar_t> cid( ::mir_utf8decodeW(data));
-
-	InviteChatParam *param = new InviteChatParam(cid, invitedContacts, this);
-	
-	if (::DialogBoxParam(
-		g_hInstance, 
-		MAKEINTRESOURCE(IDD_CHATROOM_INVITE), 
-		NULL, 
-		CSkypeProto::InviteToChatProc, 
-		(LPARAM)param) == IDOK)
-	{
-		SEStringList needToAdd;
-		for (size_t i = 0; i < param->invitedContacts.size(); i++)
-			needToAdd.append(std::string(::mir_utf8encodeW(param->invitedContacts[i])).c_str());
-
-		conversation->AddConsumers(needToAdd);
-	}
-
-	delete param;
-}
-
-void CSkypeProto::JoinToChat(CConversation::Ref conversation, bool showWindow)
-{
-	conversation->Join();
-
-	SEString data;
-
-	conversation->GetPropIdentity(data);
-	mir_ptr<wchar_t> cid( ::mir_utf8decodeW(data));
-
-	this->CreateChatWindow(conversation, showWindow);
-
-	CParticipant::Refs participants;
-	conversation->GetParticipants(participants, CConversation::OTHER_CONSUMERS);
-	for (uint i = 0; i < participants.size(); i++)
-	{
-		participants[i]->GetPropIdentity(data);
-		ptrW sid = ::mir_utf8decodeW(data);
-
-		CParticipant::RANK rank;
-		participants[i]->GetPropRank(rank);
-
-		CContact::Ref contact;
-		this->GetContact((char *)ptrA(::mir_utf8encodeW(sid)), contact);
-
-		auto status = Contact::OFFLINE;
-		contact->GetPropAvailability(status);
-
-		this->AddChatContact(
-			cid,
-			sid,
-			CSkypeProto::Roles[rank],
-			CSkypeProto::SkypeToMirandaStatus(status));
-	}
-}
-
-void CSkypeProto::AddConactsToChat(CConversation::Ref conversation, const StringList &invitedContacts)
+void CSkypeProto::LeaveChat(const wchar_t *cid)
 {
-	SEString data;
-
-	conversation->GetPropIdentity(data);
-	wchar_t *cid = ::mir_utf8decodeW(data);
-
-	StringList alreadyInChat(this->GetChatUsers(cid));
+	GC_INFO gci = {0};
+	gci.Flags = BYID | DATA;
+	gci.pszModule = this->m_szModuleName;
+	gci.pszID = ::mir_wstrdup(cid);
 
-	CParticipant::Refs participants;
-	conversation->GetParticipants(participants, CConversation::OTHER_CONSUMERS);
-	for (uint i = 0; i < participants.size(); i++)
+	if ( !::CallServiceSync(MS_GC_GETINFO, 0, (LPARAM)&gci))
 	{
-		participants[i]->GetPropIdentity(data);
-		mir_ptr<wchar_t> sid = ::mir_utf8decodeW(data);
-					
-		if (invitedContacts.contains(sid) && !alreadyInChat.contains(sid))
-		{
-			CContact::Ref contact;
-			this->GetContact((char *)ptrA(::mir_utf8encodeW(sid)), contact);
-
-			CContact::AVAILABILITY status;
-			contact->GetPropAvailability(status);
-
-			CParticipant::RANK rank;
-			participants[i]->GetPropRank(rank);
-
-			this->AddChatContact(
-				cid, 
-				sid, 
-				CSkypeProto::Roles[rank],
-				status);
-		}
+		ChatRoom *room = (ChatRoom *)gci.dwItemData;
+		room->LeaveChat();
 	}
 }
 
-void CSkypeProto::LeaveChat(const wchar_t *cid)
-{
-	mir_ptr<wchar_t> chatID( ::mir_wstrdup(cid));
-
-	GCDEST gcd = { m_szModuleName, { NULL }, GC_EVENT_CONTROL };
-	gcd.ptszID = chatID;
-
-	GCEVENT gce = {0};
-	gce.cbSize = sizeof(GCEVENT);
-	gce.dwFlags = GC_TCHAR;
-	gce.pDest = &gcd;
-	::CallServiceSync(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce);
-	::CallServiceSync(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce);
-}
-
-void CSkypeProto::RaiseChatEvent(const wchar_t *cid, const wchar_t *sid, int evt, DWORD flags, DWORD itemData, const wchar_t *status, const wchar_t *message, DWORD timestamp)
-{
-	HANDLE hContact = this->GetContactBySid(sid);
-	mir_ptr<wchar_t> nick(::db_get_wsa(hContact, this->m_szModuleName, "Nick"));
-	if (!nick)
-		nick = ::mir_wstrdup(sid);
-	/*mir_ptr<wchar_t> nick( hContact ? 
-		::mir_a2u((char *)::CallService(MS_CLIST_GETCONTACTDISPLAYNAME, WPARAM(hContact), 0)) : 
-		::mir_wstrdup(sid));*/
-
-	GCDEST gcd = { this->m_szModuleName, { NULL }, evt };
-	gcd.ptszID = ::mir_wstrdup(cid);
-
-	GCEVENT gce = {0};
-	gce.cbSize = sizeof(gce);
-	gce.dwFlags = GC_TCHAR | flags;
-	gce.pDest = &gcd;
-	gce.ptszNick = nick;
-	gce.ptszUID = sid;
-	gce.bIsMe = ::wcsicmp(sid, this->login) == 0;
-	gce.dwItemData = itemData;
-	gce.ptszStatus = status;
-	gce.ptszText = message;
-	gce.time = timestamp;
-	::CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
-}
-
-void CSkypeProto::SendChatMessage(const wchar_t *cid, const wchar_t *sid, const wchar_t *message)
-{
-	this->RaiseChatEvent(cid, sid, GC_EVENT_MESSAGE, GCEF_ADDTOLOG, 0, NULL, message);
-}
-
-void CSkypeProto::AddChatContact(const wchar_t *cid, const wchar_t *sid, const wchar_t *group, const WORD status)
-{
-	this->RaiseChatEvent(cid, sid, GC_EVENT_JOIN, 0, 0, CSkypeProto::Roles[SKYPE_CHAT_GROUP_WIRTER]);
-	this->RaiseChatEvent(cid, sid, GC_EVENT_SETCONTACTSTATUS, 0, status);
-}
-
-void CSkypeProto::KickChatContact(const wchar_t *cid, const wchar_t *sid)
-{
-	this->RaiseChatEvent(cid, sid, GC_EVENT_KICK, GCEF_ADDTOLOG);
-}
-
-void CSkypeProto::RemoveChatContact(const wchar_t *cid, const wchar_t *sid)
-{
-	this->RaiseChatEvent(cid, sid, GC_EVENT_QUIT, GCEF_ADDTOLOG);
-}
-
 INT_PTR __cdecl CSkypeProto::OnJoinChat(WPARAM wParam, LPARAM)
 {
 	HANDLE hContact = (HANDLE)wParam;
@@ -1180,7 +810,6 @@ INT_PTR __cdecl CSkypeProto::OnJoinChat(WPARAM wParam, LPARAM)
 		ptrW name = ::mir_utf8decodeW(data);
 
 		ChatRoom *room = new ChatRoom(cid, name, this);
-		this->chatList->AddChatRoom(room);
 
 		Participant::Refs participants;
 		conversation->GetParticipants(participants, Conversation::ALL);
@@ -1195,11 +824,25 @@ INT_PTR __cdecl CSkypeProto::OnLeaveChat(WPARAM wParam, LPARAM)
 {
 	HANDLE hContact = (HANDLE)wParam;
 	if (hContact)
-		this->LeaveChat( mir_ptr<wchar_t>( ::db_get_wsa(hContact, this->m_szModuleName, "ChatRoomID")));
+	{
+		ptrW cid(::db_get_wsa(hContact, this->m_szModuleName, "ChatRoomID"));
+		
+		GC_INFO gci = {0};
+		gci.Flags = BYID | DATA;
+		gci.pszModule = this->m_szModuleName;
+		gci.pszID = cid;
+
+		if ( !::CallServiceSync(MS_GC_GETINFO, 0, (LPARAM)&gci))
+		{
+			ChatRoom *room = (ChatRoom *)gci.dwItemData;
+			room->LeaveChat();
+		}
+	}
 
 	return 0;
 }
 
+
 int __cdecl CSkypeProto::OnGCEventHook(WPARAM, LPARAM lParam)
 {
 	GCHOOK *gch = (GCHOOK *)lParam;
@@ -1208,23 +851,29 @@ int __cdecl CSkypeProto::OnGCEventHook(WPARAM, LPARAM lParam)
 	if (::strcmp(gch->pDest->pszModule, this->m_szModuleName))
 		return 0;
 
-	mir_ptr<wchar_t> cid( ::mir_wstrdup(gch->pDest->ptszID));
-	mir_ptr<wchar_t> sid( ::mir_wstrdup(gch->ptszUID));
-
 	CConversation::Ref conversation;
-	switch (gch->pDest->iType) {
+	switch (gch->pDest->iType)
+	{
 	case GC_SESSION_TERMINATE:
-		if (this->GetConversationByIdentity(::mir_utf8encodeW(cid), conversation, false))
-			conversation->RetireFrom();
+		{
+			ptrA cid = ::mir_utf8encodeW(gch->pDest->ptszID);
+			if (this->GetConversationByIdentity((char *)cid, conversation, false))
+			{
+				Participant::Refs participants;
+				conversation->GetParticipants(participants, CConversation::MYSELF);
+				participants[0]->Retire();
+			}
+		}
 		break;
 
 	case GC_USER_MESSAGE:
 		if (gch->ptszText && gch->ptszText[0])
 		{
-			if (this->GetConversationByIdentity(::mir_utf8encodeW(cid), conversation, false))
+			ptrA cid = ::mir_utf8encodeW(gch->pDest->ptszID);
+			if (this->GetConversationByIdentity((char *)cid, conversation, false))
 			{
 				CMessage::Ref message;
-				mir_ptr<char> text(::mir_utf8encodeW(gch->ptszText));
+				ptrA text(::mir_utf8encodeW(gch->ptszText));
 				conversation->PostText((char *)text, message);
 			}
 		}
@@ -1239,43 +888,57 @@ int __cdecl CSkypeProto::OnGCEventHook(WPARAM, LPARAM lParam)
 		break;*/
 
 	case GC_USER_PRIVMESS:
-		::CallService(MS_MSG_SENDMESSAGE, (WPARAM)this->GetContactBySid(sid), 0);
+		{
+			::CallService(MS_MSG_SENDMESSAGE, (WPARAM)this->GetContactBySid(gch->ptszUID), 0);
+		}
 		break;
 
 	case GC_USER_LOGMENU:
-		switch(gch->dwData) {
+		switch(gch->dwData)
+		{
 		case 10:
-			if (this->GetConversationByIdentity(::mir_utf8encodeW(cid), conversation, false))
 			{
-				StringList invitedContacts(this->GetChatUsers(cid));
-				this->InviteConactsToChat(conversation, invitedContacts);
+				ptrA cid = ::mir_utf8encodeW(gch->pDest->ptszID);
+				if (this->GetConversationByIdentity((char *)cid, conversation, false))
+				{
+					StringList invitedContacts(this->GetChatUsers(gch->pDest->ptszID));
+					
+					SEStringList consumers;
+					for (size_t i = 0; i < invitedContacts.size(); i++)
+					{
+						ptrA identity(::mir_utf8encodeW(invitedContacts[i]));
+						consumers.append((char *)identity);
+					}
+					conversation->AddConsumers(consumers);
+				}
 			}
 			break;
 
 		case 20:
-			this->LeaveChat(cid);
+			this->LeaveChat(gch->pDest->ptszID);
 			break;
 		}
 		break;
 
 	case GC_USER_NICKLISTMENU:
-		switch (gch->dwData) {
+		switch (gch->dwData)
+		{
 		case 10:
-			::CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)this->GetContactBySid(sid), 0);
+			::CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)this->GetContactBySid(gch->ptszUID), 0);
 			break;
 
 		case 20:
-			CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)this->GetContactBySid(sid), 0);
+			::CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)this->GetContactBySid(gch->ptszUID), 0);
 			break;
 
 		case 110:
-			this->LeaveChat(cid);
+			this->LeaveChat(gch->pDest->ptszID);
 			break;
 		}
 		break;
 
-	case GC_USER_TYPNOTIFY:
-		break;
+	//case GC_USER_TYPNOTIFY:
+		//break;
 	}
 	return 0;
 }
@@ -1284,7 +947,15 @@ int __cdecl CSkypeProto::OnGCMenuHook(WPARAM, LPARAM lParam)
 {
 	GCMENUITEMS *gcmi = (GCMENUITEMS*) lParam;
 
-	if (gcmi == NULL || ::stricmp(gcmi->pszModule, this->m_szModuleName))
+	GC_INFO gci = {0};
+	gci.Flags = BYID | DATA;
+	gci.pszModule = gcmi->pszModule;
+
+	::CallServiceSync(MS_GC_GETINFO, 0, (LPARAM)&gci);
+
+	ChatRoom *room = (ChatRoom *)gci.dwItemData;
+
+	if (room == NULL)// || ::stricmp(gcmi->pszModule, room->ppro->m_szModuleName))
 		return 0;
 
 	if (gcmi->Type == MENU_ON_LOG)
@@ -1332,10 +1003,10 @@ void CSkypeProto::UpdateChatUserStatus(CContact::Ref contact)
 
 	SEString identity;
 	contact->GetIdentity(identity);
-	mir_ptr<wchar_t> sid( ::mir_utf8decodeW(identity));
+	ptrW sid(::mir_utf8decodeW(identity));
 
 	GC_INFO gci = {0};
-	gci.Flags = BYINDEX | ID;
+	gci.Flags = BYINDEX | DATA;
 	gci.pszModule = this->m_szModuleName;
 
 	int count = ::CallServiceSync(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)this->m_szModuleName);
@@ -1344,12 +1015,16 @@ void CSkypeProto::UpdateChatUserStatus(CContact::Ref contact)
 		gci.iItem = i;
 		::CallServiceSync(MS_GC_GETINFO, 0, (LPARAM)&gci);
 
-		this->RaiseChatEvent(
-			gci.pszID,
-			sid,
-			GC_EVENT_SETCONTACTSTATUS,
-			0,
-			CSkypeProto::SkypeToMirandaStatus(availability));
+		ChatRoom *room = (ChatRoom *)gci.dwItemData;
+		if (room != NULL)
+		{
+			room->SendEvent(
+				sid,
+				GC_EVENT_SETCONTACTSTATUS,
+				0,
+				0,
+				CSkypeProto::SkypeToMirandaStatus(availability));
+		}
 	}
 }
 
@@ -1383,7 +1058,7 @@ void __cdecl CSkypeProto::LoadChatList(void*)
 				ptrW name = ::mir_utf8decodeW(data);
 
 				ChatRoom *room = new ChatRoom(cid, name, this);
-				this->chatList->AddChatRoom(room);				
+				this->AddChatRoom(conversation);
 
 				Participant::Refs participants;
 				conversation->GetParticipants(participants, Conversation::ALL);
@@ -1396,70 +1071,19 @@ void __cdecl CSkypeProto::LoadChatList(void*)
 
 ///
 
-void CSkypeProto::OnChatMessageReceived(const ConversationRef &conversation, const MessageRef &message, uint messageType)
-{
-	SEString data;
-
-	uint timestamp;
-	message->GetPropTimestamp(timestamp);
-
-	message->GetPropBodyXml(data);
-	ptrA text = CSkypeProto::RemoveHtml(data);
-
-	message->GetPropAuthor(data);
-	ptrW sid(::mir_utf8decodeW(data));
-
-	conversation->GetPropIdentity(data);
-	ptrW cid(::mir_utf8decodeW(data));
-
-	//this->SendChatMessage(cid, sid, mir_ptr<wchar_t>(::mir_utf8decodeW(text)));
-	this->RaiseChatEvent(
-		cid, 
-		sid, 
-		messageType == CMessage::POSTED_TEXT ? GC_EVENT_MESSAGE : GC_EVENT_ACTION,
-		GCEF_ADDTOLOG, 
-		0, 
-		NULL, 
-		ptrW(::mir_utf8decodeW(text)),
-		timestamp);
-}
-
-void CSkypeProto::OnChatMessageSent(const ConversationRef &conversation, const MessageRef &message, uint messageType)
-{
-	SEString data;
-
-	uint timestamp;
-	message->GetPropTimestamp(timestamp);
-
-	message->GetPropBodyXml(data);
-	ptrA text = CSkypeProto::RemoveHtml(data);
-
-	conversation->GetPropIdentity(data);
-	ptrW cid(::mir_utf8decodeW(data));
-
-	message->GetPropAuthor(data);
-	ptrW sid(::mir_utf8decodeW(data));
-
-	//this->SendChatMessage(cid, nick, mir_ptr<wchar_t>(::mir_utf8decodeW(text)));
-	this->RaiseChatEvent(
-		cid, 
-		sid, 
-		messageType == CMessage::POSTED_TEXT ? GC_EVENT_MESSAGE : GC_EVENT_ACTION,
-		GCEF_ADDTOLOG, 
-		0, 
-		NULL, 
-		ptrW(::mir_utf8decodeW(text)),
-		timestamp);
-}
-
 void CSkypeProto::OnChatEvent(const ConversationRef &conversation, const MessageRef &message)
 {
 	uint messageType;
 	messageType = message->GetUintProp(Message::P_TYPE);
 
+	SEString data;
+	conversation->GetPropIdentity(data);
+	ptrW cid = ::mir_utf8decodeW(data);
+
 	GC_INFO gci = {0};
 	gci.Flags = BYID | DATA;
 	gci.pszModule = this->m_szModuleName;
+	gci.pszID = cid;
 
 	if ( !::CallServiceSync(MS_GC_GETINFO, 0, (LPARAM)&gci))
 	{
@@ -1477,12 +1101,13 @@ void CSkypeProto::OnChatEvent(const ConversationRef &conversation, const Message
 		ptrW name = ::mir_utf8decodeW(data);
 
 		ChatRoom *room = new ChatRoom(cid, name, this);
-		this->chatList->AddChatRoom(room);
+		this->AddChatRoom(conversation);
 
 		Participant::Refs participants;
 		conversation->GetParticipants(participants, Conversation::ALL);
 				
 		room->Start(participants, true);
+		conversation.fetch();
 	}
 }
 
@@ -1503,7 +1128,7 @@ void CSkypeProto::OnConversationListChange(
 		ptrW name = ::mir_utf8decodeW(data);
 
 		ChatRoom *room = new ChatRoom(cid, name, this);
-		this->chatList->AddChatRoom(room);
+		this->AddChatRoom(conversation);
 
 		Participant::Refs participants;
 		conversation->GetParticipants(participants, Conversation::ALL);
diff --git a/protocols/Skype/src/skype_chat.h b/protocols/Skype/src/skype_chat.h
index d12cc3fa72..134823e343 100644
--- a/protocols/Skype/src/skype_chat.h
+++ b/protocols/Skype/src/skype_chat.h
@@ -80,9 +80,6 @@ private:
 
 	inline static int CompareMembers(const ChatMember *p1, const ChatMember *p2) { return ::lstrcmpi(p1->sid, p2->sid); }
 
-	static int __cdecl OnGCEventHook(WPARAM, LPARAM lParam);
-	static int __cdecl OnGCMenuHook(WPARAM, LPARAM lParam);
-
 	void AddMember(ChatMember *member, DWORD timestamp, int flag);
 
 public:
@@ -97,8 +94,6 @@ public:
 	void SendEvent(ChatMember *member, int eventType, DWORD timestamp = time(NULL), DWORD flags = GCEF_ADDTOLOG, DWORD itemData = 0, const wchar_t *status = NULL, const wchar_t *message = NULL);
 	void SendEvent(const wchar_t *sid, int eventType, DWORD timestamp = time(NULL), DWORD flags = GCEF_ADDTOLOG, DWORD itemData = 0, const wchar_t *status = NULL, const wchar_t *message = NULL);
 
-	void AppendMessage(const wchar_t *sid, const wchar_t *message, DWORD timestamp = time(NULL), int eventType = GC_EVENT_MESSAGE);
-
 	bool IsMe(const wchar_t *sid) const;
 	bool IsMe(ChatMember *member) const;
 
@@ -117,22 +112,7 @@ public:
 	void RemoveMember(const wchar_t *sid, DWORD timestamp = time(NULL));
 
 	void OnEvent(const ConversationRef &conversation, const MessageRef &message);
-};
 
-class  ChatList
-{
-private:
-	CSkypeProto *ppro;
-	LIST<ChatRoom> chatRooms;
-
-	inline static int CompareChatRooms(const ChatRoom* p1, const ChatRoom* p2) { return ::lstrcmpi(p1->cid, p2->cid); }
-
-public:
-	ChatList(CSkypeProto *ppro);
-	~ChatList();
-
-	ChatRoom *FindChatRoom(ChatRoom *item);
-	ChatRoom *FindChatRoom(const wchar_t *cid);
-
-	HANDLE AddChatRoom(ChatRoom *item);
+	static int __cdecl OnGCEventHook(WPARAM, LPARAM lParam);
+	static int __cdecl OnGCMenuHook(WPARAM, LPARAM lParam);
 };
\ No newline at end of file
diff --git a/protocols/Skype/src/skype_contacts.cpp b/protocols/Skype/src/skype_contacts.cpp
index 79afd6b3e4..a8f7877647 100644
--- a/protocols/Skype/src/skype_contacts.cpp
+++ b/protocols/Skype/src/skype_contacts.cpp
@@ -200,7 +200,7 @@ HANDLE CSkypeProto::GetContactFromAuthEvent(HANDLE hEvent)
 
 HANDLE CSkypeProto::AddContact(CContact::Ref contact)
 {
-	mir_ptr<wchar_t> sid( ::mir_utf8decodeW(contact->GetSid()));
+	ptrW sid(::mir_utf8decodeW(contact->GetSid()));
 
 	CContact::AVAILABILITY availability;
 	contact->GetPropAvailability(availability);
@@ -211,7 +211,7 @@ HANDLE CSkypeProto::AddContact(CContact::Ref contact)
 		hContact = (HANDLE)::CallService(MS_DB_CONTACT_ADD, 0, 0);
 		::CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)this->m_szModuleName);
 
-		mir_ptr<wchar_t> nick(::mir_utf8decodeW(contact->GetNick()));
+		ptrW nick(::mir_utf8decodeW(contact->GetNick()));
 
 		switch(availability) 
 		{
diff --git a/protocols/Skype/src/skype_proto.cpp b/protocols/Skype/src/skype_proto.cpp
index 455979e506..fad767da3e 100644
--- a/protocols/Skype/src/skype_proto.cpp
+++ b/protocols/Skype/src/skype_proto.cpp
@@ -149,7 +149,7 @@ HANDLE __cdecl CSkypeProto::FileAllow( HANDLE hContact, HANDLE hTransfer, const
 { 
 	uint oid = (uint)hTransfer;
 
-	CMessage *message = this->newMessage(oid);
+	MessageRef message(oid);
 
 	this->Log(L"Incoming file transfer is accepted");
 	CTransfer::Refs transfers;
@@ -157,18 +157,17 @@ HANDLE __cdecl CSkypeProto::FileAllow( HANDLE hContact, HANDLE hTransfer, const
 	for (uint i = 0; i < transfers.size(); i++)
 	{
 		bool success;
-		SEString name;
 		wchar_t fullPath[MAX_PATH] = {0};
-		transfers[i]->GetPropFilename(name);
-		::mir_sntprintf(fullPath, MAX_PATH, L"%s%s", szPath, ::mir_utf8decodeW(name));
+
+		SEString data;
+		transfers[i]->GetPropFilename(data);
+		ptrW name(::mir_utf8decodeW(data));
+		::mir_sntprintf(fullPath, MAX_PATH, L"%s%s", szPath, name);
 		if (!transfers[i]->Accept(::mir_u2a(fullPath), success) || !success)
 		{
-			delete message;
 			return 0;
 		}
 	}
-	
-	delete message;
 
 	return hTransfer; 
 }
diff --git a/protocols/Skype/src/skype_proto.h b/protocols/Skype/src/skype_proto.h
index ae9bc979f4..487cd925dd 100644
--- a/protocols/Skype/src/skype_proto.h
+++ b/protocols/Skype/src/skype_proto.h
@@ -266,7 +266,6 @@ protected:
 	void	OnTransferChanged(CTransfer::Ref transfer, int prop);
 
 	// chat
-	ChatList *chatList;
 	static wchar_t* Roles[];
 
 	bool IsChatRoom(HANDLE hContact);
@@ -282,30 +281,18 @@ protected:
 	void GetInvitedContacts(HANDLE hItem, HWND hwndList, StringList &invitedContacts);
 
 	void InitChat();
-	CConversation::Ref StartChat();
-	CConversation::Ref StartChat(StringList &invitedContacts);
-	void LeaveChat(const wchar_t *cid);
-
-	void CreateChatWindow(CConversation::Ref conversation, bool showWindow = true);
-
-	void JoinToChat(CConversation::Ref conversation, bool showWindow = true);
-	void InviteConactsToChat(CConversation::Ref conversation, const StringList &invitedContacts);
-	void AddConactsToChat(CConversation::Ref conversation, const StringList &invitedContacts);
+	
+	void StartChat();
+	void StartChat(StringList &invitedContacts);
 
-	void RaiseChatEvent(const wchar_t *cid, const wchar_t *sid, int evt, DWORD flags = 0x0001, DWORD itemData = 0, const wchar_t *status = NULL, const wchar_t *message = NULL, DWORD timestamp = time(NULL));
-	void SendChatMessage(const wchar_t *cid, const wchar_t *sid, const wchar_t *message);
-	void AddChatContact(const wchar_t *cid, const wchar_t *sid, const wchar_t *group, const WORD status = ID_STATUS_ONLINE);
-	void KickChatContact(const wchar_t *cid, const wchar_t *sid);
-	void RemoveChatContact(const wchar_t *cid, const wchar_t *sid);	
+	void LeaveChat(const wchar_t *cid);
 
 	INT_PTR __cdecl OnJoinChat(WPARAM wParam, LPARAM);
 	INT_PTR __cdecl OnLeaveChat(WPARAM wParam, LPARAM);
 
-	int __cdecl OnGCMenuHook(WPARAM, LPARAM lParam);
 	int __cdecl OnGCEventHook(WPARAM, LPARAM lParam);
-	
-	void	OnChatMessageSent(const ConversationRef &conversation, const MessageRef &message, uint messageType);
-	void	OnChatMessageReceived(const ConversationRef &conversation, const MessageRef &message, uint messageType);
+	int __cdecl OnGCMenuHook(WPARAM, LPARAM lParam);
+
 	void	OnChatEvent(const ConversationRef &conversation, const MessageRef &message);
 
 	// contacts
diff --git a/protocols/Skype/src/skype_transfers.cpp b/protocols/Skype/src/skype_transfers.cpp
index 13e1c1a5b3..0b2a4286fa 100644
--- a/protocols/Skype/src/skype_transfers.cpp
+++ b/protocols/Skype/src/skype_transfers.cpp
@@ -124,7 +124,7 @@ void CSkypeProto::OnFileEvent(const ConversationRef &conversation, const Message
 
 				SEString data;
 				transfer->GetPropPartnerHandle(data);
-				HANDLE hContact = this->GetContactBySid(mir_ptr<wchar_t>(::mir_utf8decodeW(data)));
+				HANDLE hContact = this->GetContactBySid(ptrW(::mir_utf8decodeW(data)));
 
 				transfer->GetPropFilename(data);
 				wchar_t *path = ::mir_utf8decodeW(data);
-- 
cgit v1.2.3