From 5cad65e7fb3f8ffaad2355d0b85d980cc5ef07c3 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Sun, 9 Jun 2013 22:21:47 +0000 Subject: Skype: - fixed logout from chat on miranda closing (#362) - added new chat command (moderation and etc.) - some improvements git-svn-id: http://svn.miranda-ng.org/main/trunk@4905 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Skype/src/skype_account.cpp | 2 +- protocols/Skype/src/skype_chat.cpp | 623 +++++++++++++++++++++----------- protocols/Skype/src/skype_chat.h | 109 ++++-- protocols/Skype/src/skype_contacts.cpp | 16 +- protocols/Skype/src/skype_events.cpp | 15 +- protocols/Skype/src/skype_instances.cpp | 4 +- protocols/Skype/src/skype_messages.cpp | 12 +- protocols/Skype/src/skype_profile.cpp | 3 +- protocols/Skype/src/skype_proto.h | 7 +- protocols/Skype/src/skype_runtime.cpp | 66 +++- protocols/Skype/src/skype_utils.cpp | 12 + 11 files changed, 611 insertions(+), 258 deletions(-) diff --git a/protocols/Skype/src/skype_account.cpp b/protocols/Skype/src/skype_account.cpp index bbdb402aad..3bdc8d023c 100644 --- a/protocols/Skype/src/skype_account.cpp +++ b/protocols/Skype/src/skype_account.cpp @@ -131,7 +131,7 @@ void CSkypeProto::LogOut() { this->account->SetAvailability(CContact::OFFLINE); this->Log(L"Logout from account"); - //this->account->Logout(true); + this->account->Logout(true); this->SetAllContactStatus(ID_STATUS_OFFLINE); } diff --git a/protocols/Skype/src/skype_chat.cpp b/protocols/Skype/src/skype_chat.cpp index 370bb3b982..50786daea9 100644 --- a/protocols/Skype/src/skype_chat.cpp +++ b/protocols/Skype/src/skype_chat.cpp @@ -3,7 +3,7 @@ #include #include -enum NICK_LIST_MENU +enum CHAT_LIST_MENU { ICM_CANCEL, @@ -17,25 +17,46 @@ enum NICK_LIST_MENU static struct gc_item crListItems[] = { - { LPGENT("&User details"), ICM_DETAILS, MENU_ITEM, FALSE }, -// { LPGENT("&Request auth"), ICM_AUTH_REQUEST, MENU_ITEM, TRUE }, - { NULL, 0, MENU_SEPARATOR, FALSE }, -// { LPGENT("Invite to conferance"), ICM_CONF_INVITE, MENU_ITEM, TRUE }, -// { NULL, 0, MENU_SEPARATOR, FALSE }, - { LPGENT("Set &role"), ICM_ROLE, MENU_NEWPOPUP, TRUE }, - { LPGENT("&Administrator"), ICM_ROLE_ADMIN, MENU_POPUPITEM, TRUE }, - { LPGENT("&Speaker"), ICM_ROLE_SPEAKER, MENU_POPUPITEM, TRUE }, - { LPGENT("&Writer"), ICM_ROLE_WRITER, MENU_POPUPITEM, TRUE }, - { LPGENT("&Listener"), ICM_ROLE_SPECTATOR, MENU_POPUPITEM, TRUE }, - { NULL, 0, MENU_SEPARATOR, FALSE }, - { LPGENT("&Kick"), ICM_KICK, MENU_ITEM, TRUE }, - { LPGENT("Outlaw (&ban)"), ICM_BAN, MENU_ITEM, TRUE }, - { NULL, 0, MENU_SEPARATOR, FALSE }, - { LPGENT("Copy &skypename"), ICM_COPY_SID, MENU_ITEM, FALSE }, - { LPGENT("Copy room &uri"), ICM_COPY_URI, MENU_ITEM, FALSE } + { LPGENT("&User details"), ICM_DETAILS, MENU_ITEM }, + { LPGENT("&Request auth"), ICM_AUTH_REQUEST, MENU_ITEM }, + { NULL, 0, MENU_SEPARATOR }, + { LPGENT("Invite to conferance"), ICM_CONF_INVITE, MENU_ITEM }, + { NULL, 0, MENU_SEPARATOR }, + { LPGENT("Set &role"), ICM_ROLE, MENU_NEWPOPUP }, + { LPGENT("&Administrator"), ICM_ROLE_ADMIN, MENU_POPUPITEM }, + { LPGENT("&Speaker"), ICM_ROLE_SPEAKER, MENU_POPUPITEM }, + { LPGENT("&Writer"), ICM_ROLE_WRITER, MENU_POPUPITEM }, + { LPGENT("&Listener"), ICM_ROLE_SPECTATOR, MENU_POPUPITEM }, + { NULL, 0, MENU_SEPARATOR }, + { LPGENT("&Kick"), ICM_KICK, MENU_ITEM }, + { LPGENT("Outlaw (&ban)"), ICM_BAN, MENU_ITEM }, + { NULL, 0, MENU_SEPARATOR }, + { LPGENT("Copy &skypename"), ICM_COPY_SID, MENU_ITEM }, + { LPGENT("Copy room &uri"), ICM_COPY_URI, MENU_ITEM } }; -static const COLORREF crCols[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; +static void DisableChatMenuItem(CHAT_LIST_MENU disabledId) +{ + for (int i = 0; i < SIZEOF(crListItems); i++) + { + if (crListItems[i].dwID == disabledId) + crListItems[i].bDisabled = TRUE; + } +} + +static void DisableChatMenuItems(CHAT_LIST_MENU disabledIds[]) +{ + for (int i = 0; i < SIZEOF(disabledIds); i++) + DisableChatMenuItem(disabledIds[i]); +} + +static void ResetChatMenuItem() +{ + for (int i = 0; i < SIZEOF(crListItems); i++) + crListItems[i].bDisabled = FALSE; +} + +static const COLORREF crCols[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; void CSkypeProto::InitChat() { @@ -60,13 +81,12 @@ wchar_t *ChatRoom::Roles[] = L"", // --- L"Creator", // CREATOR = 1 L"Master", // ADMIN = 2 - L"Helper", // SPEAKER = 3 - L"User", // WRITER = 4 - L"Listener", // SPECTATOR= 5 + L"Speaker", // SPEAKER = 3 + L"Writer", // WRITER = 4 + L"Spectator", // SPECTATOR= 5 L"Applicant", // APPLICANT= 6 L"Retried", // RETIRED = 7 L"Outlaw", // OUTLAW = 8 - //L"Ghost" // ??? }; ChatRoom::ChatRoom(const wchar_t *cid) : members(1, CompareMembers) @@ -83,7 +103,9 @@ ChatRoom::ChatRoom(const wchar_t *cid, const wchar_t *name, CSkypeProto *ppro) : this->ppro = ppro; // this->me = new ChatMember(ppro->login); - this->me->nick = ::mir_wstrdup(::TranslateT("me")); + this->me->SetNick(::TranslateT("me")); + this->me->SetRank(0); + this->me->SetStatus(ID_STATUS_OFFLINE); } ChatRoom::~ChatRoom() @@ -94,6 +116,9 @@ ChatRoom::~ChatRoom() ::mir_free(this->name); if (this->me != NULL) delete this->me; + for (int i = 0; i < this->members.getCount(); i++) + delete this->members[i]; + this->members.destroy(); } void ChatRoom::Start(bool showWindow) @@ -119,7 +144,7 @@ void ChatRoom::Start(bool showWindow) gce.cbSize = sizeof(GCEVENT); gce.dwFlags = GC_TCHAR; gce.pDest = &gcd; - for (int i = 1; i < SIZEOF(ChatRoom::Roles) - 3; i++) + for (int i = 1; i < SIZEOF(ChatRoom::Roles); i++) { gce.ptszStatus = ::TranslateW(ChatRoom::Roles[i]); ::CallServiceSync(MS_GC_EVENT, NULL, (LPARAM)&gce); @@ -144,25 +169,27 @@ void ChatRoom::Start(const ParticipantRefs &participants, bool showWindow) participant->GetPropIdentity(data); ptrW sid = ::mir_utf8decodeW(data); - ChatMember *member = new ChatMember(sid); - member->rank = participant->GetUintProp(Participant::P_RANK); + ChatMember member(sid); + member.SetRank(participant->GetUintProp(Participant::P_RANK)); Contact::Ref contact; this->ppro->GetContact(data, contact); Contact::AVAILABILITY status; contact->GetPropAvailability(status); - member->status = CSkypeProto::SkypeToMirandaStatus(status); + member.SetStatus(CSkypeProto::SkypeToMirandaStatus(status)); contact->GetPropFullname(data); if (data.length() != 0) - member->nick = ::mir_utf8decodeW(data); - else - member->nick = ::mir_wstrdup(sid); + { + ptrW nick = ::mir_utf8decodeW(data); + member.SetNick(nick); + } + + member.SetPaticipant(participant); + member.participant.fetch(); - member->participant = participant; - member->participant.fetch(); - this->AddMember(member); + this->AddMember(member, NULL, NULL); } } @@ -179,19 +206,19 @@ void ChatRoom::LeaveChat() ::CallServiceSync(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce); } -void ChatRoom::SendEvent(ChatMember *member, int eventType, DWORD timestamp, DWORD flags, DWORD itemData, const wchar_t *status, const wchar_t *message) +void ChatRoom::SendEvent(const ChatMember &item, int eventType, DWORD timestamp, DWORD flags, DWORD itemData, const wchar_t *status, const wchar_t *message) { GCDEST gcd = { ppro->m_szModuleName, { NULL }, eventType }; gcd.ptszID = this->cid; - bool isMe = this->IsMe(member->sid); + bool isMe = this->IsMe(item); GCEVENT gce = {0}; gce.cbSize = sizeof(gce); gce.dwFlags = GC_TCHAR | flags; gce.pDest = &gcd; - gce.ptszUID = member->sid; - gce.ptszNick = !isMe ? member->nick : ::TranslateT("me"); + gce.ptszUID = item.GetSid(); + gce.ptszNick = !isMe ? item.GetNick() : ::TranslateT("me"); gce.bIsMe = isMe; gce.dwItemData = itemData; gce.ptszStatus = status; @@ -207,122 +234,147 @@ void ChatRoom::SendEvent(const wchar_t *sid, int eventType, DWORD timestamp, DWO ChatMember search(sid); ChatMember *member = this->members.find(&search); if (member != NULL) - this->SendEvent(member, eventType, timestamp, flags, itemData, status, message); + this->SendEvent(*member, eventType, timestamp, flags, itemData, status, message); } else - this->SendEvent(this->me, eventType, timestamp, flags, itemData, status, message); + this->SendEvent(*this->me, eventType, timestamp, flags, itemData, status, message); } bool ChatRoom::IsMe(const wchar_t *sid) const { - return ::lstrcmpi(this->me->sid, sid) == 0; + return ::lstrcmpi(this->ppro->login, sid) == 0; } -bool ChatRoom::IsMe(ChatMember *member) const +bool ChatRoom::IsMe(const ChatMember &item) const { - return this->IsMe(member->sid); -} - -ChatMember *ChatRoom::FindChatMember(ChatMember *item) -{ - return this->members.find(item); + return ::lstrcmpi(this->ppro->login, item.GetSid()) == 0; } ChatMember *ChatRoom::FindChatMember(const wchar_t *sid) { - ChatMember search(sid); - return this->members.find(&search); + if ( !IsMe(sid)) + { + ChatMember search(sid); + return this->members.find(&search); + } + else + return this->me; } -void ChatRoom::AddMember(ChatMember *item, DWORD timestamp, int flags) +void ChatRoom::AddMember(const ChatMember &item, const ChatMember *author, DWORD timestamp) { if ( !this->IsMe(item)) { - ChatMember *member = this->members.find(item); + ChatMember *member = this->FindChatMember(item.GetSid()); if (member != NULL) { - this->UpdateMember(item->sid, item->nick, item->rank, item->status, timestamp, flags); - member = item; + this->UpdateMember(item, timestamp); } else { - this->members.insert(item); - - this->SendEvent(item, GC_EVENT_JOIN, timestamp, flags, 0, ChatRoom::Roles[item->rank]); - this->SendEvent(item, GC_EVENT_SETCONTACTSTATUS, timestamp, 0, item->status); + this->members.insert(new ChatMember(item)); + + this->SendEvent(item, GC_EVENT_JOIN, timestamp, GCEF_ADDTOLOG, 0, ::TranslateW(ChatRoom::Roles[item.GetRank()])); + this->SendEvent(item, GC_EVENT_SETCONTACTSTATUS, timestamp, 0, item.GetStatus()); } } else { - if (this->me->rank != item->rank) + if (this->me->GetRank() != item.GetRank()) { - wchar_t *oldStatus = ::TranslateW(ChatRoom::Roles[item->rank]); - this->SendEvent(this->me, GC_EVENT_REMOVESTATUS, timestamp, 0, 0, oldStatus); - this->me->rank = item->rank; - wchar_t *newStatus = ::TranslateW(ChatRoom::Roles[item->rank]); - this->SendEvent(this->me, GC_EVENT_ADDSTATUS, timestamp, flags, 0, newStatus); + this->SendEvent(*this->me, GC_EVENT_REMOVESTATUS, timestamp, 0, 0, ::TranslateW(ChatRoom::Roles[this->me->GetRank()])); + this->SendEvent(*this->me, GC_EVENT_ADDSTATUS, timestamp, !this->me->GetRank() ? 0 : GCEF_ADDTOLOG, 0, ::TranslateW(ChatRoom::Roles[item.GetRank()]), author == NULL ? NULL : author->GetNick()); + this->me->SetRank(item.GetRank()); } } } -void ChatRoom::AddMember(ChatMember *item, DWORD timestamp) +void ChatRoom::UpdateMember(const wchar_t *sid, const wchar_t *nick, int rank, int status, DWORD timestamp) { - this->AddMember(item, timestamp, GCEF_ADDTOLOG); -} - -void ChatRoom::AddMember(ChatMember *item) -{ - this->AddMember(item, NULL, 0); + ChatMember search(sid); + ChatMember *member = this->members.find(&search); + if (member != NULL) + { + if (::lstrcmp(member->GetNick(), nick) != 0) + { + this->SendEvent(*member, GC_EVENT_NICK, timestamp, GCEF_ADDTOLOG, 0, nick); + member->SetNick(nick); + } + if (member->GetRank() != rank) + { + this->SendEvent(*member, GC_EVENT_REMOVESTATUS, timestamp, 0, 0, ::TranslateW(ChatRoom::Roles[member->GetRank()])); + this->SendEvent(*member, GC_EVENT_ADDSTATUS, timestamp, GCEF_ADDTOLOG, 0, ::TranslateW(ChatRoom::Roles[rank])); + member->SetRank(rank); + } + if (member->GetStatus() != status) + { + this->SendEvent(*member, GC_EVENT_SETCONTACTSTATUS, timestamp, 0, status); + member->SetStatus(status); + } + } } -void ChatRoom::UpdateMember(const wchar_t *sid, const wchar_t *nick, int rank, int status, DWORD timestamp, DWORD flags) +void ChatRoom::UpdateMember(const ChatMember &item, DWORD timestamp) { - ChatMember search(sid); - ChatMember *member = this->members.find(&search); + ChatMember *member = this->FindChatMember(item.GetSid()); if (member != NULL) { - if (::lstrcmp(member->nick, nick) != 0) - this->SendEvent(member, GC_EVENT_NICK, timestamp, flags, 0, nick); - if (member->rank != rank) + ptrW nick(item.GetNick()); + if (::lstrcmp(member->GetNick(), nick) != 0) + { + this->SendEvent(*member, GC_EVENT_NICK, timestamp, GCEF_ADDTOLOG, 0, nick); + member->SetNick(nick); + } + if (member->GetRank() != item.GetRank()) + { + this->SendEvent(*member, GC_EVENT_REMOVESTATUS, timestamp, 0, 0, ::TranslateW(ChatRoom::Roles[member->GetRank()])); + this->SendEvent(*member, GC_EVENT_ADDSTATUS, timestamp, GCEF_ADDTOLOG, 0, ::TranslateW(ChatRoom::Roles[item.GetRank()])); + member->SetRank(item.GetRank()); + } + if (member->GetStatus() != item.GetStatus()) { - ptrW oldStatus = ::TranslateW(ChatRoom::Roles[member->rank]); - this->SendEvent(member, GC_EVENT_REMOVESTATUS, timestamp, 0, 0, oldStatus); - ptrW newStatus = ::TranslateW(ChatRoom::Roles[rank]); - this->SendEvent(member, GC_EVENT_ADDSTATUS, timestamp, flags, 0, newStatus); + this->SendEvent(*member, GC_EVENT_SETCONTACTSTATUS, timestamp, 0, item.GetStatus()); + member->SetStatus(item.GetStatus()); } - if (member->status != status) - this->SendEvent(member, GC_EVENT_SETCONTACTSTATUS, timestamp, 0, status); } } -void ChatRoom::KickMember(ChatMember *member, const ChatMember *kicker, DWORD timestamp) +void ChatRoom::KickMember(const ChatMember &item, const ChatMember *author, DWORD timestamp) { - if ( !this->IsMe(member)) + if ( !this->IsMe(item)) { - if (this->members.getIndex(member) >= 0) + ChatMember *member = this->FindChatMember(item.GetSid()); + if (member != NULL) { - this->SendEvent(member, GC_EVENT_KICK, timestamp, GCEF_ADDTOLOG, 0, kicker->nick); + this->SendEvent(*member, GC_EVENT_KICK, timestamp, GCEF_ADDTOLOG, 0, author->GetNick()); this->members.remove(member); + delete member; } } else { - this->SendEvent(this->me, GC_EVENT_KICK, timestamp, GCEF_ADDTOLOG, 0, kicker->nick); + this->SendEvent(*this->me, GC_EVENT_KICK, timestamp, GCEF_ADDTOLOG, 0, author->GetNick()); + this->me->SetRank(/*APPLICANT= */6); } } -void ChatRoom::KickMember(const wchar_t *sid, const wchar_t *kickerSid, DWORD timestamp) +void ChatRoom::KickMember(const wchar_t *sid, const wchar_t *author, DWORD timestamp) { ChatMember member(sid); - this->KickMember(&member, this->FindChatMember(kickerSid), timestamp); + this->KickMember(member, this->FindChatMember(author), timestamp); } -void ChatRoom::RemoveMember(ChatMember *member, DWORD timestamp) +void ChatRoom::RemoveMember(const ChatMember &item, DWORD timestamp) { - if ( !this->IsMe(member)) + if ( !this->IsMe(item)) { - if (this->members.indexOf(member) >= 0) - this->SendEvent(member, GC_EVENT_QUIT, timestamp, GCEF_ADDTOLOG); + ChatMember *member = this->FindChatMember(item.GetSid()); + if (member != NULL) + { + this->SendEvent(*member, GC_EVENT_QUIT, timestamp); + this->members.remove(member); + delete member; + } } else this->LeaveChat(); @@ -331,7 +383,7 @@ void ChatRoom::RemoveMember(ChatMember *member, DWORD timestamp) void ChatRoom::RemoveMember(const wchar_t *sid, DWORD timestamp) { ChatMember member(sid); - this->RemoveMember(&member, timestamp); + this->RemoveMember(member, timestamp); } void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &message) @@ -371,33 +423,46 @@ void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &me { SEString data; + /*Message::CONSUMPTION_STATUS status; + message->GetPropConsumptionStatus(status); + if (status == Message::UNCONSUMED_NORMAL)*/ { uint timestamp; message->GetPropTimestamp(timestamp); + message->GetPropAuthor(data); + ChatMember *author = this->FindChatMember((wchar_t *)ptrW(::mir_utf8decodeW(data))); + ParticipantRefs participants; conversation->GetParticipants(participants); - for (size_t i = 0; i < participants.size(); i++) { participants[i]->GetPropIdentity(data); ptrW sid(::mir_utf8decodeW(data)); if (this->FindChatMember(sid) == NULL) { - ChatMember *member = new ChatMember(sid); - member->rank = participants[i]->GetUintProp(Participant::P_RANK); + ChatMember member(sid); + member.SetRank(participants[i]->GetUintProp(Participant::P_RANK)); Contact::Ref contact; this->ppro->GetContact(data, contact); Contact::AVAILABILITY status; contact->GetPropAvailability(status); - member->status = CSkypeProto::SkypeToMirandaStatus(status); + member.SetStatus(CSkypeProto::SkypeToMirandaStatus(status)); contact->GetPropFullname(data); - member->nick = ::mir_utf8decodeW(data); + ptrW nick(::mir_utf8decodeW(data)); + if (data.length() != 0) + { + ptrW nick = ::mir_utf8decodeW(data); + member.SetNick(nick); + } + + member.participant = participants[i]; + member.participant.fetch(); - this->AddMember(member); + this->AddMember(member, author, timestamp); } } @@ -450,12 +515,15 @@ void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &me { SEString data; + /*Message::CONSUMPTION_STATUS status; + message->GetPropConsumptionStatus(status); + if (status == Message::UNCONSUMED_NORMAL)*/ { uint timestamp; message->GetPropTimestamp(timestamp); message->GetPropAuthor(data); - ptrW sid = ::mir_utf8decodeW(data); + ptrW author = ::mir_utf8decodeW(data); message->GetPropIdentities(data); char *identities = ::mir_strdup(data); @@ -466,7 +534,8 @@ void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &me { do { - this->KickMember(ptrW(::mir_utf8decodeW(identity)), sid, timestamp); + ptrW sid(::mir_utf8decodeW(identity)); + this->KickMember(sid, author, timestamp); identity = ::strtok(NULL, " "); } @@ -482,6 +551,9 @@ void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &me { SEString data; + Message::CONSUMPTION_STATUS status; + message->GetPropConsumptionStatus(status); + if (status == Message::UNCONSUMED_NORMAL) { uint timestamp; message->GetPropTimestamp(timestamp); @@ -501,6 +573,9 @@ void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &me ptrA text = ::mir_strdup(data); int i = 0; + /*Message::CONSUMPTION_STATUS status; + message->GetPropConsumptionStatus(status); + if (status == Message::UNCONSUMED_NORMAL)*/ { message->GetPropAuthor(data); ptrW sid = ::mir_utf8decodeW(data); @@ -515,7 +590,7 @@ void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &me message->GetPropBodyXml(data); ptrW rank = ::mir_utf8decodeW(data); - member->rank = 0; + member->SetRank(0); } } } @@ -525,6 +600,11 @@ void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &me { SEString data; + Message::CONSUMPTION_STATUS status; + message->GetPropConsumptionStatus(status); + if (status != Message::UNCONSUMED_NORMAL) + break; + message->GetPropAuthor(data); ptrW sid = ::mir_utf8decodeW(data); @@ -546,6 +626,11 @@ void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &me { SEString data; + Message::CONSUMPTION_STATUS status; + message->GetPropConsumptionStatus(status); + if (status != Message::UNCONSUMED_NORMAL) + break; + message->GetPropAuthor(data); ptrW sid = ::mir_utf8decodeW(data); @@ -569,10 +654,9 @@ void ChatRoom::OnEvent(const ConversationRef &conversation, const MessageRef &me void CSkypeProto::ChatValidateContact(HANDLE hItem, HWND hwndList, const StringList &contacts) { - //HANDLE hContact = (HANDLE)::SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXT, (LPARAM)hItem); if (this->IsProtoContact(hItem) && !this->IsChatRoom(hItem)) { - mir_ptr sid( ::db_get_wsa(hItem, this->m_szModuleName, SKYPE_SETTINGS_LOGIN)); + ptrW sid( ::db_get_wsa(hItem, this->m_szModuleName, SKYPE_SETTINGS_LOGIN)); if (sid == NULL || contacts.contains(sid)) ::SendMessage(hwndList, CLM_DELETEITEM, (WPARAM)hItem, 0); } @@ -714,7 +798,6 @@ INT_PTR CALLBACK CSkypeProto::InviteToChatProc(HWND hwndDlg, UINT msg, WPARAM wP if ( !param->invitedContacts.empty()) { - //SetWindowLongPtr(hwndDlg, 0, (LONG_PTR)bct); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); ::EndDialog(hwndDlg, IDOK); } @@ -734,7 +817,7 @@ INT_PTR CALLBACK CSkypeProto::InviteToChatProc(HWND hwndDlg, UINT msg, WPARAM wP bool CSkypeProto::IsChatRoom(HANDLE hContact) { - return ::db_get_b(hContact, this->m_szModuleName, "ChatRoom", 0) > 0; + return ::db_get_b(hContact, this->m_szModuleName, "ChatRoom", 0) == 1; } HANDLE CSkypeProto::GetChatRoomByCid(const wchar_t *cid) @@ -745,10 +828,10 @@ HANDLE CSkypeProto::GetChatRoomByCid(const wchar_t *cid) for (hContact = ::db_find_first(this->m_szModuleName); hContact; hContact = ::db_find_next(hContact, this->m_szModuleName)) { - if (this->IsChatRoom(hContact)) + if (this->IsChatRoom(hContact)) { - mir_ptr chatID(::db_get_wsa(hContact, this->m_szModuleName, "ChatRoomID")); - if (::lstrcmp(cid, chatID) == 0) + ptrW chatSid( ::db_get_wsa(hContact, this->m_szModuleName, SKYPE_SETTINGS_LOGIN)); + if (::lstrcmpi(chatSid, cid) == 0) break; } } @@ -774,9 +857,13 @@ HANDLE CSkypeProto::AddChatRoom(CConversation::Ref conversation) conversation->GetPropDisplayname(data); ptrW name = ::mir_utf8decodeW(data); + conversation->GetJoinBlob(data); + ptrW joinBlob = ::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, "JoinBlob", joinBlob); ::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); @@ -840,56 +927,6 @@ void CSkypeProto::LeaveChat(const wchar_t *cid) } } -INT_PTR __cdecl CSkypeProto::OnJoinChat(WPARAM wParam, LPARAM) -{ - HANDLE hContact = (HANDLE)wParam; - if (hContact) - { - ptrW cid(::db_get_wsa(hContact, this->m_szModuleName, "ChatRoomID")); - - SEString data; - CConversation::Ref conversation; - - this->GetConversationByIdentity(::mir_utf8encodeW(cid), conversation); - - conversation->GetPropDisplayname(data); - ptrW name = ::mir_utf8decodeW(data); - - ChatRoom *room = new ChatRoom(cid, name, this); - room->conversation = conversation; - - Participant::Refs participants; - conversation->GetParticipants(participants, Conversation::ALL); - - room->Start(participants, true); - } - - return 0; -} - -INT_PTR __cdecl CSkypeProto::OnLeaveChat(WPARAM wParam, LPARAM) -{ - HANDLE hContact = (HANDLE)wParam; - if (hContact) - { - 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; @@ -898,10 +935,21 @@ int __cdecl CSkypeProto::OnGCEventHook(WPARAM, LPARAM lParam) if (::strcmp(gch->pDest->pszModule, this->m_szModuleName)) return 0; - CConversation::Ref conversation; + GC_INFO gci = {0}; + gci.Flags = BYID | DATA; + gci.pszModule = gch->pDest->pszModule; + gci.pszID = gch->pDest->ptszID; + + ::CallServiceSync(MS_GC_GETINFO, 0, (LPARAM)&gci); + + ChatRoom *room = (ChatRoom *)gci.dwItemData; + + if (room == NULL) + return 0; + switch (gch->pDest->iType) { - case GC_SESSION_TERMINATE: + /*case GC_SESSION_TERMINATE: { ptrA cid = ::mir_utf8encodeW(gch->pDest->ptszID); if (this->GetConversationByIdentity((char *)cid, conversation, false)) @@ -911,18 +959,14 @@ int __cdecl CSkypeProto::OnGCEventHook(WPARAM, LPARAM lParam) participants[0]->Retire(); } } - break; + break;*/ case GC_USER_MESSAGE: if (gch->ptszText && gch->ptszText[0]) { - ptrA cid = ::mir_utf8encodeW(gch->pDest->ptszID); - if (this->GetConversationByIdentity((char *)cid, conversation, false)) - { - CMessage::Ref message; - ptrA text(::mir_utf8encodeW(gch->ptszText)); - conversation->PostText((char *)text, message); - } + CMessage::Ref message; + ptrA text(::mir_utf8encodeW(gch->ptszText)); + room->conversation->PostText((char *)text, message); } break; @@ -941,41 +985,108 @@ int __cdecl CSkypeProto::OnGCEventHook(WPARAM, LPARAM lParam) break; case GC_USER_LOGMENU: - switch(gch->dwData) + case GC_USER_NICKLISTMENU: + switch (gch->dwData) { - case 10: + case CHAT_LIST_MENU::ICM_ROLE_ADMIN: + case CHAT_LIST_MENU::ICM_ROLE_SPEAKER: + case CHAT_LIST_MENU::ICM_ROLE_WRITER: + case CHAT_LIST_MENU::ICM_ROLE_SPECTATOR: { - ptrA cid = ::mir_utf8encodeW(gch->pDest->ptszID); - if (this->GetConversationByIdentity((char *)cid, conversation, false)) + ChatMember *member = room->FindChatMember(gch->ptszUID); + if (member != NULL) { - StringList invitedContacts(this->GetChatUsers(gch->pDest->ptszID)); - - SEStringList consumers; - for (size_t i = 0; i < invitedContacts.size(); i++) + Participant::RANK rank; + switch (gch->dwData) + { + case CHAT_LIST_MENU::ICM_ROLE_ADMIN: + rank = Participant::ADMIN; + break; + + case CHAT_LIST_MENU::ICM_ROLE_SPEAKER: + rank = Participant::SPEAKER; + break; + + case CHAT_LIST_MENU::ICM_ROLE_WRITER: + rank = Participant::WRITER; + break; + + case CHAT_LIST_MENU::ICM_ROLE_SPECTATOR: + rank = Participant::SPECTATOR; + break; + } + if (member->participant && member->participant->SetRankTo(rank)) { - ptrA identity(::mir_utf8encodeW(invitedContacts[i])); - consumers.append((char *)identity); + member->SetRank(rank); + room->UpdateMember(member->GetSid(), member->GetNick(), rank, member->GetStatus()); } - conversation->AddConsumers(consumers); } } break; - case 20: - this->LeaveChat(gch->pDest->ptszID); + case CHAT_LIST_MENU::ICM_KICK: + { + ChatMember *member = room->FindChatMember(gch->ptszUID); + if (member != NULL) + { + if (member->participant && member->participant->Retire()) + room->KickMember(gch->ptszUID, room->me->GetSid()); + } + } break; - } - break; - case GC_USER_NICKLISTMENU: - switch (gch->dwData) - { - case NICK_LIST_MENU::ICM_DETAILS: + case CHAT_LIST_MENU::ICM_BAN: + { + ChatMember *member = room->FindChatMember(gch->ptszUID); + if (member != NULL && member->participant) + { + member->participant->SetRankTo(Participant::OUTLAW); + if (member->participant->Retire()) + room->KickMember(gch->ptszUID, room->me->GetSid()); + } + } + break; + + case CHAT_LIST_MENU::ICM_AUTH_REQUEST: + { + CContact::Ref contact; + SEString sid((char *)ptrA(::mir_utf8encodeW(gch->ptszUID))); + if (this->GetContact(sid, contact)) + { + this->AuthRequest( + this->AddContact(contact), + LPGENT("Hi! I\'d like to add you to my contact list")); + } + } + break; + + case CHAT_LIST_MENU::ICM_DETAILS: ::CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)this->GetContactBySid(gch->ptszUID), 0); break; - case 110: - this->LeaveChat(gch->pDest->ptszID); + case CHAT_LIST_MENU::ICM_COPY_SID: + { + HANDLE hContact = this->GetContactBySid(gch->ptszUID); + if (!hContact) + { + ptrW sid = ::db_get_wsa(hContact, this->m_szModuleName, SKYPE_SETTINGS_LOGIN); + if (sid != NULL) + CSkypeProto::CopyToClipboard(sid); + } + } + break; + + case CHAT_LIST_MENU::ICM_COPY_URI: + { + SEString data; + room->conversation->GetJoinBlob(data); + ptrW blob = ::mir_utf8decodeW(data); + + wchar_t uri[MAX_PATH]; + ::mir_sntprintf(uri, SIZEOF(uri), L"skype:?chat&blob=%s", blob); + + CSkypeProto::CopyToClipboard(uri); + } break; } break; @@ -1002,29 +1113,43 @@ int __cdecl CSkypeProto::OnGCMenuHook(WPARAM, LPARAM lParam) if (room == NULL || ::stricmp(gcmi->pszModule, this->m_szModuleName)) return 0; - if (gcmi->Type == MENU_ON_LOG) + ResetChatMenuItem(); + + /*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; + gcmi->nItems = SIZEOF(crListItems); + gcmi->Item = crListItems; } 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;*/ gcmi->nItems = SIZEOF(crListItems); gcmi->Item = crListItems; + }*/ + + if (room->me->GetRank() >= Participant::APPLICANT) + { + DisableChatMenuItem(ICM_CONF_INVITE); } + if (gcmi->pszUID == NULL || this->GetContactBySid(gcmi->pszUID) != NULL) + { + DisableChatMenuItem(ICM_AUTH_REQUEST); + DisableChatMenuItem(ICM_COPY_SID); + } + + if (room->me->GetRank() > Participant::ADMIN && room->me->GetRank() == 0) + { + //CHAT_LIST_MENU adminItems[] = { ICM_ROLE, ICM_ROLE_ADMIN, ICM_ROLE_SPEAKER, ICM_ROLE_WRITER, ICM_ROLE_SPECTATOR }; + //DisableChatMenuItems(adminItems); + + DisableChatMenuItem(ICM_ROLE); + DisableChatMenuItem(ICM_KICK); + DisableChatMenuItem(ICM_BAN); + } + + gcmi->nItems = SIZEOF(crListItems); + gcmi->Item = crListItems; + return 0; } @@ -1074,6 +1199,66 @@ void CSkypeProto::UpdateChatUserStatus(CContact::Ref contact) } } +INT_PTR __cdecl CSkypeProto::OnJoinChat(WPARAM wParam, LPARAM) +{ + HANDLE hContact = (HANDLE)wParam; + if (hContact) + { + ptrW joinBlob(::db_get_wsa(hContact, this->m_szModuleName, "JoinBlob")); + ptrW cid(::db_get_wsa(hContact, this->m_szModuleName, SKYPE_SETTINGS_LOGIN)); + + SEString data; + ConversationRef conversation; + + this->GetConversationByBlob(::mir_utf8encodeW(joinBlob), conversation); + //this->GetConversationByIdentity(::mir_utf8encodeW(cid), conversation); + if (conversation) + { + //conversation->Join(); + + conversation->GetPropDisplayname(data); + ptrW name(::mir_utf8decodeW(data)); + + /*conversation->GetPropIdentity(data); + ptrW cid(::mir_utf8decodeW(data));*/ + + ChatRoom *room = new ChatRoom(cid, name, this); + room->conversation = conversation; + //room->conversation.fetch(); + + Participant::Refs participants; + conversation->GetParticipants(participants, Conversation::ALL); + + room->Start(participants, true); + } + } + + return 0; +} + +INT_PTR __cdecl CSkypeProto::OnLeaveChat(WPARAM wParam, LPARAM) +{ + HANDLE hContact = (HANDLE)wParam; + if (hContact) + { + ptrW cid(::db_get_wsa(hContact, this->m_szModuleName, SKYPE_SETTINGS_LOGIN)); + + 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->conversation->RetireFrom(); + room->LeaveChat(); + } + } + + return 0; +} + /// void __cdecl CSkypeProto::LoadChatList(void*) @@ -1138,7 +1323,7 @@ void CSkypeProto::OnChatEvent(const ConversationRef &conversation, const Message ChatRoom *room = (ChatRoom *)gci.dwItemData; room->OnEvent(conversation, message); } - else + else if(messageType != Message::RETIRED || messageType != Message::RETIRED_OTHERS) { SEString data; @@ -1173,17 +1358,23 @@ void CSkypeProto::OnConversationListChange( conversation->GetPropIdentity(data); ptrW cid = ::mir_utf8decodeW(data); - conversation->GetPropDisplayname(data); - ptrW name = ::mir_utf8decodeW(data); + if ( !this->GetChatRoomByCid(cid)) + { + conversation->GetPropIdentity(data); + ptrW cid = ::mir_utf8decodeW(data); - ChatRoom *room = new ChatRoom(cid, name, this); - room->conversation = conversation; - //room->conversation.fetch(); - this->AddChatRoom(conversation); + conversation->GetPropDisplayname(data); + ptrW name = ::mir_utf8decodeW(data); - Participant::Refs participants; - conversation->GetParticipants(participants, Conversation::ALL); + ChatRoom *room = new ChatRoom(cid, name, this); + room->conversation = conversation; + //room->conversation.fetch(); + this->AddChatRoom(conversation); + + Participant::Refs participants; + conversation->GetParticipants(participants, Conversation::ALL); - room->Start(participants, true); + room->Start(participants, true); + } } } \ No newline at end of file diff --git a/protocols/Skype/src/skype_chat.h b/protocols/Skype/src/skype_chat.h index 75fec78dcd..d070cb0b44 100644 --- a/protocols/Skype/src/skype_chat.h +++ b/protocols/Skype/src/skype_chat.h @@ -5,12 +5,13 @@ class ChatMember { -public: +private: wchar_t *sid; wchar_t *nick; int rank; WORD status; +public: CParticipant::Ref participant; ChatMember() @@ -25,6 +26,13 @@ public: this->nick = NULL; } + ChatMember(const ChatMember &other) + { + this->sid = NULL; + this->nick = NULL; + this->operator=(other); + } + ~ChatMember() { if (this->sid != NULL) @@ -33,6 +41,57 @@ public: ::mir_free(this->nick); } + void SetNick(const wchar_t *nick) + { + if (this->nick != NULL) + ::mir_free(this->nick); + this->nick = ::mir_wstrdup(nick); + } + + wchar_t *GetSid() const + { + return this->sid; + } + + wchar_t *GetNick() const + { + if (this->nick == NULL) + return this->sid; + + return this->nick; + } + + void SetRank(int rank) + { + this->rank = rank; + } + + int GetRank() const + { + return this->rank; + } + + void SetStatus(int status) + { + this->status = status; + } + + int GetStatus() const + { + return this->status; + } + + void SetPaticipant(const ParticipantRef &participant) + { + this->participant = participant; + //this->participant.fetch(); + } + + static int Compare(const ChatMember *p1, const ChatMember *p2) + { + return ::lstrcmpi(p1->sid, p2->sid); + } + bool operator==(const ChatMember &other) const { return ::lstrcmp(this->sid, other.sid) == 0; @@ -43,17 +102,22 @@ public: return !(*this == other); } - ChatMember& operator=(const ChatMember& right) + ChatMember& operator=(const ChatMember &other) { - if (this == &right) + if (this == &other) return *this; - ::mir_free(this->sid); - ::mir_free(this->nick); - this->sid = ::mir_wstrdup(right.sid); - this->nick = ::mir_wstrdup(right.nick); - this->rank = right.rank; - this->status = right.status; + if (this->sid != NULL) + ::mir_free(this->sid); + this->sid = ::mir_wstrdup(other.sid); + + if (this->nick != NULL) + ::mir_free(this->nick); + this->nick = ::mir_wstrdup(other.nick); + + this->rank = other.rank; + this->status = other.status; + this->participant = other.participant; return *this; } }; @@ -66,7 +130,7 @@ private: HANDLE hContact; - ChatMember *me; + LIST members; @@ -78,11 +142,17 @@ private: HANDLE AddChatRoom(); - inline static int CompareMembers(const ChatMember *p1, const ChatMember *p2) { return ::lstrcmpi(p1->sid, p2->sid); } + inline static int CompareMembers(const ChatMember *p1, const ChatMember *p2) { return ChatMember::Compare(p1, p2); } - void AddMember(ChatMember *member, DWORD timestamp, int flag); + bool IsMe(const ChatMember &item) const; + void SendEvent(const ChatMember &item, int eventType, DWORD timestamp = time(NULL), DWORD flags = GCEF_ADDTOLOG, DWORD itemData = 0, const wchar_t *status = NULL, const wchar_t *message = NULL); + + void UpdateMember(const ChatMember &item, DWORD timestamp = time(NULL)); + void KickMember(const ChatMember &item, const ChatMember *author, DWORD timestamp = time(NULL)); + void RemoveMember(const ChatMember &item, DWORD timestamp = time(NULL)); public: + ChatMember *me; CConversation::Ref conversation; ChatRoom(const wchar_t *cid, const wchar_t *name, CSkypeProto *ppro); @@ -93,24 +163,17 @@ public: void LeaveChat(); - 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); bool IsMe(const wchar_t *sid) const; - bool IsMe(ChatMember *member) const; - ChatMember *FindChatMember(ChatMember *item); + // ChatMember *FindChatMember(const wchar_t *sid); - void AddMember(ChatMember *member, DWORD timestamp); - void AddMember(ChatMember *member); - - void UpdateMember(const wchar_t *sid, const wchar_t *nick, int rank, int status, DWORD timestamp = time(NULL), DWORD flags = GCEF_ADDTOLOG); - - void KickMember(ChatMember *member, const ChatMember *kicker, DWORD timestamp = time(NULL)); - void KickMember(const wchar_t *sid, const wchar_t *kicker, DWORD timestamp = time(NULL)); + void AddMember(const ChatMember &item, const ChatMember *author, DWORD timestamp = time(NULL)); - void RemoveMember(ChatMember *member, DWORD timestamp = time(NULL)); + void UpdateMember(const wchar_t *sid, const wchar_t *nick, int rank, int status, DWORD timestamp = time(NULL)); + void KickMember(const wchar_t *sid, const wchar_t *author, DWORD timestamp = time(NULL)); void RemoveMember(const wchar_t *sid, DWORD timestamp = time(NULL)); void OnEvent(const ConversationRef &conversation, const MessageRef &message); diff --git a/protocols/Skype/src/skype_contacts.cpp b/protocols/Skype/src/skype_contacts.cpp index a8f7877647..35c61d6357 100644 --- a/protocols/Skype/src/skype_contacts.cpp +++ b/protocols/Skype/src/skype_contacts.cpp @@ -44,10 +44,18 @@ void CSkypeProto::UpdateContactStatus(HANDLE hContact, CContact::Ref contact) } } +void CSkypeProto::UpdateContactClient(SEObject *obj, HANDLE hContact) +{ + bool isMobile = false; + ((CContact *)obj)->HasCapability(Contact::CAPABILITY_MOBILE_DEVICE, isMobile/*, true*/); + + ::db_set_ws(hContact, this->m_szModuleName, "MirVer", isMobile ? L"SkypeMobile" : L"Skype"); +} + void CSkypeProto::UpdateContactNickName(SEObject *obj, HANDLE hContact) { // todo: P_DISPLAYNAME = 21 is unworked - mir_ptr nick( ::mir_utf8decodeW(obj->GetStrProp(/* *::P_FULLNAME */ 5))); + ptrW nick( ::mir_utf8decodeW(obj->GetStrProp(/* *::P_FULLNAME */ 5))); if ( !::wcslen(nick)) ::db_unset(hContact, this->m_szModuleName, "Nick"); else @@ -167,7 +175,7 @@ HANDLE CSkypeProto::GetContactBySid(const wchar_t *sid) { if ( !this->IsChatRoom(hContact)) { - mir_ptr contactSid( ::db_get_wsa(hContact, this->m_szModuleName, SKYPE_SETTINGS_LOGIN)); + ptrW contactSid( ::db_get_wsa(hContact, this->m_szModuleName, SKYPE_SETTINGS_LOGIN)); if (::lstrcmpi(contactSid, sid) == 0) break; } @@ -276,8 +284,8 @@ void __cdecl CSkypeProto::LoadContactList(void* data) // todo: move to AddContact? this->UpdateContactAuthState(hContact, contact); this->UpdateContactStatus(hContact, contact); - - mir_ptr nick( ::db_get_wsa(hContact, "CList", "MyHandle")); + + ptrW nick( ::db_get_wsa(hContact, "CList", "MyHandle")); if ( !nick || !::wcslen(nick)) { nick = ::mir_utf8decodeW(contact->GetNick()); diff --git a/protocols/Skype/src/skype_events.cpp b/protocols/Skype/src/skype_events.cpp index 86e275f691..e889326d8d 100644 --- a/protocols/Skype/src/skype_events.cpp +++ b/protocols/Skype/src/skype_events.cpp @@ -60,13 +60,16 @@ int CSkypeProto::OnContactDeleted(WPARAM wParam, LPARAM lParam) { if (this->IsChatRoom(hContact)) { - ptrW chatID(::db_get_wsa(hContact, this->m_szModuleName, "ChatRoomID")); + ptrW chatID(::db_get_wsa(hContact, this->m_szModuleName, SKYPE_SETTINGS_LOGIN)); this->LeaveChat(chatID); - CConversation::Ref conversation; + ConversationRef conversation; this->GetConversationByIdentity(::mir_utf8encodeW(chatID), conversation); - conversation->RetireFrom(); - conversation->Delete(); + if (conversation) + { + conversation->RetireFrom(); + conversation->Delete(); + } } else this->RevokeAuth(wParam, lParam); @@ -178,7 +181,7 @@ int __cdecl CSkypeProto::OnTabSRMMButtonPressed(WPARAM wParam, LPARAM lParam) case BBB_ID_CONF_INVITE: if (this->IsOnline() && this->IsChatRoom(hContact)) { - StringList targets = this->GetChatUsers(mir_ptr(::db_get_wsa(hContact, this->m_szModuleName, "ChatRoomID"))); + StringList targets = this->GetChatUsers(ptrW(::db_get_wsa(hContact, this->m_szModuleName, SKYPE_SETTINGS_LOGIN))); this->StartChat(targets); } @@ -188,7 +191,7 @@ int __cdecl CSkypeProto::OnTabSRMMButtonPressed(WPARAM wParam, LPARAM lParam) if (this->IsOnline() && !this->IsChatRoom(hContact)) { StringList targets; - targets.insert( mir_ptr(::db_get_wsa(hContact, this->m_szModuleName, SKYPE_SETTINGS_LOGIN))); + targets.insert(ptrW(::db_get_wsa(hContact, this->m_szModuleName, SKYPE_SETTINGS_LOGIN))); this->StartChat(targets); } diff --git a/protocols/Skype/src/skype_instances.cpp b/protocols/Skype/src/skype_instances.cpp index aef0cb6e1e..935ecf73d0 100644 --- a/protocols/Skype/src/skype_instances.cpp +++ b/protocols/Skype/src/skype_instances.cpp @@ -41,14 +41,14 @@ CSkypeProto* CSkypeProto::InitSkypeProto(const char* protoName, const wchar_t* u return NULL; } - ::mir_free(keyPair); - if ( !ppro->start()) { ::MessageBox(NULL, TranslateT("SkypeKit did not start."), _T(MODULE), MB_OK | MB_ICONERROR); return NULL; } + ::mir_free(keyPair); + CSkypeProto::instanceList.insert(ppro); return ppro; diff --git a/protocols/Skype/src/skype_messages.cpp b/protocols/Skype/src/skype_messages.cpp index d5fda0cde2..8a52946627 100644 --- a/protocols/Skype/src/skype_messages.cpp +++ b/protocols/Skype/src/skype_messages.cpp @@ -136,7 +136,7 @@ void CSkypeProto::OnMessageEvent(const ConversationRef &conversation, const Mess SEString author; message->GetPropAuthor(author); - if (::wcsicmp(mir_ptr(::mir_utf8decodeW(author)), this->login) == 0) + if (::wcsicmp(ptrW(::mir_utf8decodeW(author)), this->login) == 0) this->OnMessageSent(conversation, message); else this->OnMessageReceived(conversation, message); @@ -145,6 +145,11 @@ void CSkypeProto::OnMessageEvent(const ConversationRef &conversation, const Mess case CMessage::STARTED_LIVESESSION: { + Message::CONSUMPTION_STATUS status; + message->GetPropConsumptionStatus(status); + if (status != Message::UNCONSUMED_NORMAL) + break; + uint timestamp; message->GetPropTimestamp(timestamp); @@ -174,6 +179,11 @@ void CSkypeProto::OnMessageEvent(const ConversationRef &conversation, const Mess case CMessage::ENDED_LIVESESSION: { + Message::CONSUMPTION_STATUS status; + message->GetPropConsumptionStatus(status); + if (status != Message::UNCONSUMED_NORMAL) + break; + uint timestamp; message->GetPropTimestamp(timestamp); diff --git a/protocols/Skype/src/skype_profile.cpp b/protocols/Skype/src/skype_profile.cpp index c2ba3babdc..391dbff192 100644 --- a/protocols/Skype/src/skype_profile.cpp +++ b/protocols/Skype/src/skype_profile.cpp @@ -298,7 +298,8 @@ void CSkypeProto::UpdateProfile(SEObject *obj, HANDLE hContact) this->UpdateContactOnlineSinceTime(obj, hContact); this->UpdateContactLastEventDate(obj, hContact); - ::db_set_ws(hContact, this->m_szModuleName, "MirVer", L"Skype"); + this->UpdateContactClient(obj, hContact); + //::db_set_ws(hContact, this->m_szModuleName, "MirVer", L"Skype"); } ::db_set_dw(hContact, this->m_szModuleName, "ProfileTS", newTS); diff --git a/protocols/Skype/src/skype_proto.h b/protocols/Skype/src/skype_proto.h index 9ddf7238fe..07dccd1d3f 100644 --- a/protocols/Skype/src/skype_proto.h +++ b/protocols/Skype/src/skype_proto.h @@ -297,6 +297,8 @@ protected: void UpdateContactAuthState(HANDLE hContact, CContact::Ref contact); void UpdateContactAvatar(HANDLE hContact, CContact::Ref contact); void UpdateContactStatus(HANDLE hContact, CContact::Ref contact); + void UpdateContactClient(SEObject *obj, HANDLE hContact); + void UpdateContactNickName(SEObject *obj, HANDLE hContact); void UpdateContactOnlineSinceTime(SEObject *obj, HANDLE hContact); void UpdateContactLastEventDate(SEObject *obj, HANDLE hContact); @@ -371,6 +373,8 @@ protected: static void ShowNotification(const wchar_t *message, int flags = 0, HANDLE hContact = NULL); static void ShowNotification(const wchar_t *caption, const wchar_t *message, int flags = 0, HANDLE hContact = NULL); + static void CopyToClipboard(const wchar_t *text); + // languages static std::map languages; @@ -459,7 +463,8 @@ protected: // skype runtime char *LoadKeyPair(); int StartSkypeRuntime(const wchar_t *profileName); - void CSkypeProto::StopSkypeRuntime(); + BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode); + void StopSkypeRuntime(); // events int __cdecl OnModulesLoaded(WPARAM, LPARAM); diff --git a/protocols/Skype/src/skype_runtime.cpp b/protocols/Skype/src/skype_runtime.cpp index 9d319ac7cd..a0ead3e663 100644 --- a/protocols/Skype/src/skype_runtime.cpp +++ b/protocols/Skype/src/skype_runtime.cpp @@ -88,15 +88,75 @@ int CSkypeProto::StartSkypeRuntime(const wchar_t *profileName) return startingrt; } +BOOL CSkypeProto::SafeTerminateProcess(HANDLE hProcess, UINT uExitCode) +{ + DWORD dwTID, dwCode, dwErr = 0; + HANDLE hProcessDup = INVALID_HANDLE_VALUE; + HANDLE hRT = NULL; + HINSTANCE hKernel = ::GetModuleHandle(L"Kernel32"); + BOOL bSuccess = FALSE; + + BOOL bDup = ::DuplicateHandle( + ::GetCurrentProcess(), + hProcess, + GetCurrentProcess(), + &hProcessDup, + PROCESS_ALL_ACCESS, + FALSE, + 0); + + // Detect the special case where the process is + // already dead... + if (::GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) && (dwCode == STILL_ACTIVE)) + { + FARPROC pfnExitProc; + + pfnExitProc = GetProcAddress(hKernel, "ExitProcess"); + + hRT = ::CreateRemoteThread( + (bDup) ? hProcessDup : hProcess, + NULL, + 0, + (LPTHREAD_START_ROUTINE)pfnExitProc, + (PVOID)uExitCode, 0, &dwTID); + + if ( hRT == NULL ) + dwErr = GetLastError(); + } + else + dwErr = ERROR_PROCESS_ABORTED; + + if (hRT) + { + // Must wait process to terminate to + // guarantee that it has exited... + ::WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE); + + ::CloseHandle(hRT); + bSuccess = TRUE; + } + + if ( bDup ) + ::CloseHandle(hProcessDup); + + if ( !bSuccess ) + ::SetLastError(dwErr); + + return bSuccess; +} + void CSkypeProto::StopSkypeRuntime() { - ::PostThreadMessage(this->skypeKitProcessInfo.dwThreadId, WM_CLOSE, 0, 0); - ::WaitForSingleObject(this->skypeKitProcessInfo.hProcess, 1500); + //DWORD dwExitCode = 0; + //this->SafeTerminateProcess(this->skypeKitProcessInfo.hProcess, 0); + //::PostThreadMessage(this->skypeKitProcessInfo.dwThreadId, WM_CLOSE, 0, 0); + //::WaitForSingleObject(this->skypeKitProcessInfo.hProcess, 1500); DWORD dwExitCode = 0; ::GetExitCodeProcess(this->skypeKitProcessInfo.hProcess, &dwExitCode); if (dwExitCode == STILL_ACTIVE) - ::TerminateProcess(this->skypeKitProcessInfo.hProcess, 0); // Zero is the exit code + //::TerminateProcess(this->skypeKitProcessInfo.hProcess, 0); // Zero is the exit code + this->SafeTerminateProcess(this->skypeKitProcessInfo.hProcess, 0); ::CloseHandle(this->skypeKitProcessInfo.hThread); ::CloseHandle(this->skypeKitProcessInfo.hProcess); diff --git a/protocols/Skype/src/skype_utils.cpp b/protocols/Skype/src/skype_utils.cpp index 491d32d68e..fbb5fb5f02 100644 --- a/protocols/Skype/src/skype_utils.cpp +++ b/protocols/Skype/src/skype_utils.cpp @@ -531,3 +531,15 @@ bool CSkypeProto::FileExists(wchar_t *path) return false; } +void CSkypeProto::CopyToClipboard(const wchar_t *text) +{ + HWND hwnd = (HWND)CallService(MS_CLUI_GETHWND, 0, 0); + ::OpenClipboard(hwnd); + ::EmptyClipboard(); + HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, sizeof(TCHAR)*(::lstrlen(text)+1)); + TCHAR *s = (TCHAR *)::GlobalLock(hMem); + ::lstrcpy(s, text); + ::GlobalUnlock(hMem); + ::SetClipboardData(CF_UNICODETEXT, hMem); + ::CloseClipboard(); +} \ No newline at end of file -- cgit v1.2.3