From 8aded02eb09d418873002ea6d3e41d4d700e7e07 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Sun, 7 Oct 2012 13:47:03 +0000 Subject: - added first approach of contfct adding/deleting git-svn-id: http://svn.miranda-ng.org/main/trunk@1801 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Skype/Skype.vcxproj | 1 + protocols/Skype/Skype.vcxproj.filters | 3 + protocols/Skype/src/skype_contacts.cpp | 672 +++++++++++++++++++++++------- protocols/Skype/src/skype_database.cpp | 55 +++ protocols/Skype/src/skype_events.cpp | 7 + protocols/Skype/src/skype_proto.cpp | 101 ++++- protocols/Skype/src/skype_proto.h | 54 ++- protocols/Skype/src/skype_settings.cpp | 10 +- protocols/Skype/src/skype_subclassing.cpp | 42 +- protocols/Skype/src/skype_subclassing.h | 31 +- 10 files changed, 783 insertions(+), 193 deletions(-) create mode 100644 protocols/Skype/src/skype_database.cpp (limited to 'protocols') diff --git a/protocols/Skype/Skype.vcxproj b/protocols/Skype/Skype.vcxproj index 42e8d79222..ea3f41c52e 100644 --- a/protocols/Skype/Skype.vcxproj +++ b/protocols/Skype/Skype.vcxproj @@ -106,6 +106,7 @@ + diff --git a/protocols/Skype/Skype.vcxproj.filters b/protocols/Skype/Skype.vcxproj.filters index 82e61c86f6..e44c53eb09 100644 --- a/protocols/Skype/Skype.vcxproj.filters +++ b/protocols/Skype/Skype.vcxproj.filters @@ -51,6 +51,9 @@ Source Files + + Source Files + diff --git a/protocols/Skype/src/skype_contacts.cpp b/protocols/Skype/src/skype_contacts.cpp index fd1d6afe1d..55fdb90b3d 100644 --- a/protocols/Skype/src/skype_contacts.cpp +++ b/protocols/Skype/src/skype_contacts.cpp @@ -1,27 +1,449 @@ #include "skype_proto.h" -void CSkypeProto::OnContactChanged(CContact* contact, int prop) +void CSkypeProto::UpdateContactAboutText(HANDLE hContact, CContact::Ref contact) { - if (prop == CContact::P_AVAILABILITY) + SEString data; + contact->GetPropAbout(data); + wchar_t* aboutText = ::mir_utf8decodeW((const char*)data); + if (wcscmp(aboutText, L"") == 0) + this->DeleteSetting(hContact, "About"); + else + this->SetSettingString(hContact, "About", aboutText); + ::mir_free(aboutText); +} + +void CSkypeProto::UpdateContactAuthState(HANDLE hContact, CContact::Ref contact) +{ + uint newTS = 0; + contact->GetPropAuthreqTimestamp(newTS); + DWORD oldTS = this->GetSettingDword(hContact, "AuthTS"); + if (newTS > oldTS) + { + CContact::AVAILABILITY data; + contact->GetPropAvailability(data); + this->SetSettingWord(hContact, SKYPE_SETTINGS_STATUS, this->SkypeToMirandaStatus(data)); + + if (data == CContact::PENDINGAUTH) + this->SetSettingWord(hContact, "Auth", 1); + else + this->DeleteSetting(hContact, "Auth"); + + this->SetSettingDword(hContact, "AuthTS", newTS); + } +} + +void CSkypeProto::UpdateContactAvatar(HANDLE hContact, CContact::Ref contact) +{ + uint newTS = 0; + contact->GetPropAvatarTimestamp(newTS); + DWORD oldTS = this->GetSettingDword(hContact, "AvatarTS"); + if (newTS > oldTS) + { + SEBinary data; + contact->GetPropAvatarImage(data); + + if (data.size() > 0) + { + wchar_t* path = this->GetAvatarFilePath(this->GetSettingString(hContact, "SkypeName")); + FILE* fp = _wfopen(path, L"w"); + if (fp) + { + for (uint i = 0; i < data.size(); i++) + { + if (i) + fputc(',', fp); + fputc('\'', fp); + switch(data[i]) + { + case '\n': + fputc('\\', fp); + fputc('n', fp); + break; + + default: + fputc(data[i], fp); + } + } + CloseHandle(fp); + } + } + // todo: need to register avatar to contact + this->SetSettingDword(hContact, "AvatarTS", newTS); + } +} + +void CSkypeProto::UpdateContactBirthday(HANDLE hContact, CContact::Ref contact) +{ + uint data; + contact->GetPropBirthday(data); + if (data > 0) + { + struct tm* ptm; + time_t timeGMT = (time_t)data; + ptm = gmtime(&timeGMT); + this->SetSettingByte(hContact, "BirthDay", ptm->tm_mday); + this->SetSettingByte(hContact, "BirthMonth", ptm->tm_mon); + // todo: fix stupid year constant + this->SetSettingWord(hContact, "BirthYear", ptm->tm_year + 1917); + } + else + { + this->DeleteSetting(hContact, "BirthDay"); + this->DeleteSetting(hContact, "BirthMonth"); + this->DeleteSetting(hContact, "BirthYear"); + } +} + +void CSkypeProto::UpdateContactCity(HANDLE hContact, CContact::Ref contact) +{ + SEString data; + contact->GetPropCity(data); + wchar_t* city = ::mir_a2u((const char*)data); + if (wcscmp(city, L"") == 0) + this->DeleteSetting(hContact, "City"); + else + this->SetSettingString(hContact, "City", city); + ::mir_free(city); +} + +void CSkypeProto::UpdateContactCountry(HANDLE hContact, CContact::Ref contact) +{ + // country (en, ru, etc) + SEString data; + contact->GetPropCountry(data); + // todo: write me + //BYTE countryId = this->GetCountryIdByName((const char*)sData); + //this->SetSettingByte(hContact, "Country", countryId); +} + +void CSkypeProto::UpdateContactEmails(HANDLE hContact, CContact::Ref contact) +{ + SEString data; + contact->GetPropEmails(data); + wchar_t* emails = ::mir_a2u((const char*)data); + if (wcscmp(emails, L"") == 0) + { + this->DeleteSetting(hContact, "e-mail0"); + this->DeleteSetting(hContact, "e-mail1"); + this->DeleteSetting(hContact, "e-mail2"); + } + else + { + wchar_t* p = wcstok(emails, L" "); + if (p == NULL) + { + this->SetSettingString(hContact, "e-mail0", emails); + } + else + { + this->SetSettingString(hContact, "e-mail0", p); + p = wcstok(NULL, L" "); + if (p) this->SetSettingString(hContact, "e-mail1", p); + p = wcstok(NULL, L" "); + if (p) this->SetSettingString(hContact, "e-mail2", p); + } + } + ::mir_free(emails); +} + +void CSkypeProto::UpdateContactGender(HANDLE hContact, CContact::Ref contact) +{ + uint data; + contact->GetPropGender(data); + if (data) + this->SetSettingByte(hContact, "Gender", (BYTE)(data == 1 ? 'M' : 'F')); + else + this->DeleteSetting(hContact, "Gender"); +} + +void CSkypeProto::UpdateContactHomepage(HANDLE hContact, CContact::Ref contact) +{ + SEString data; + contact->GetPropHomepage(data); + wchar_t* homepage = ::mir_a2u((const char*)data); + if (wcscmp(homepage, L"") == 0) + this->DeleteSetting(hContact, "Homepage"); + else + this->SetSettingString(hContact, "Homepage", homepage); + ::mir_free(homepage); +} + +void CSkypeProto::UpdateContactLanguages(HANDLE hContact, CContact::Ref contact) +{ + // sanguages (en, ru, etc), space searated + SEString data; + contact->GetPropLanguages(data); + // todo: write me +} + +void CSkypeProto::UpdateContactMobilePhone(HANDLE hContact, CContact::Ref contact) +{ + SEString data; + contact->GetPropPhoneMobile(data); + wchar_t* phone = ::mir_a2u((const char*)data); + if (wcscmp(phone, L"") == 0) + this->DeleteSetting(hContact, "Cellular"); + else + this->SetSettingString(hContact, "Cellular", phone); + ::mir_free(phone); +} + +void CSkypeProto::UpdateContactPhone(HANDLE hContact, CContact::Ref contact) +{ + SEString data; + contact->GetPropPhoneHome(data); + wchar_t* phone = ::mir_a2u((const char*)data); + if (wcscmp(phone, L"") == 0) + this->DeleteSetting(hContact, "Phone"); + else + this->SetSettingString(hContact, "Phone", phone); + ::mir_free(phone); +} + +void CSkypeProto::UpdateContactOfficePhone(HANDLE hContact, CContact::Ref contact) +{ + SEString data; + contact->GetPropPhoneOffice(data); + wchar_t* phone = ::mir_a2u((const char*)data); + if (wcscmp(phone, L"") == 0) + this->DeleteSetting(hContact, "CompanyPhone"); + else + this->SetSettingString(hContact, "CompanyPhone", phone); + ::mir_free(phone); +} + +void CSkypeProto::UpdateContactState(HANDLE hContact, CContact::Ref contact) +{ + SEString data; + contact->GetPropProvince(data); + wchar_t* state = ::mir_a2u((const char*)data); + if (wcscmp(state, L"") == 0) + this->DeleteSetting(hContact, "State"); + else + this->SetSettingString(hContact, "State", state); + ::mir_free(state); +} + +void CSkypeProto::UpdateContactStatus(HANDLE hContact, CContact::Ref contact) +{ + CContact::AVAILABILITY availability; + contact->GetPropAvailability(availability); + this->SetSettingWord(hContact, SKYPE_SETTINGS_STATUS, this->SkypeToMirandaStatus(availability)); +} + +void CSkypeProto::UpdateContactStatusMessage(HANDLE hContact, CContact::Ref contact) +{ + uint newTS = 0; + contact->GetPropMoodTimestamp(newTS); + DWORD oldTS = this->GetSettingDword(hContact, "XStatusTS"); + if (newTS > oldTS) { SEString data; + contact->GetPropMoodText(data); + wchar_t* status = ::mir_utf8decodeW((const char*)data); + if (wcscmp(status, L"") == 0) + this->DeleteSetting(hContact, "XStatusMsg"); + else + this->SetSettingString(hContact, "XStatusMsg", status); + ::mir_free(status); + this->SetSettingDword(hContact, "XStatusTS", newTS); + } +} - contact->GetPropSkypename(data); - wchar_t* skypeName = ::mir_a2u((const char*)data); +void CSkypeProto::UpdateContactTimezone(HANDLE hContact, CContact::Ref contact) +{ + uint data; + contact->GetPropTimezone(data); + // todo: check me + if (data > 0) + this->SetSettingByte(hContact, "TimeZone", (data - 24*3600) / 3600); + else + this->DeleteSetting(hContact, "TimeZone"); +} + +void CSkypeProto::UpdateContactProfile(HANDLE hContact, CContact::Ref contact) +{ + uint newTS = 0; + contact->GetPropProfileTimestamp(newTS); + DWORD oldTS = this->GetSettingDword(hContact, "ProfileTS"); + if (newTS > oldTS) + { + this->UpdateContactAboutText(hContact, contact); + this->UpdateContactBirthday(hContact, contact); + this->UpdateContactCity(hContact, contact); + this->UpdateContactCountry(hContact, contact); + this->UpdateContactEmails(hContact, contact); + this->UpdateContactGender(hContact, contact); + this->UpdateContactHomepage(hContact, contact); + this->UpdateContactLanguages(hContact, contact); + this->UpdateContactMobilePhone(hContact, contact); + this->UpdateContactPhone(hContact, contact); + this->UpdateContactOfficePhone(hContact, contact); + this->UpdateContactState(hContact, contact); + this->UpdateContactTimezone(hContact, contact); + + this->SetSettingDword(hContact, "ProfileTS", newTS); + } +} + +void CSkypeProto::OnContactChanged(CContact::Ref contact, int prop) +{ + SEString data; + contact->GetPropSkypename(data); + wchar_t* sid = ::mir_a2u((const char*)data); + HANDLE hContact = this->GetContactBySid(sid); - HANDLE hContact = this->GetContactBySkypeName(skypeName); - if (hContact) + if (hContact) + { + switch(prop) { - CContact::AVAILABILITY availability; - contact->GetPropAvailability(availability); - this->SetSettingWord(hContact, SKYPE_SETTINGS_STATUS, this->SkypeToMirandaStatus(availability)); - - if (availability == CContact::PENDINGAUTH) - this->SetSettingWord(hContact, "Auth", 1); - else - this->DeleteSetting(hContact, "Auth"); + case CContact::P_ABOUT: + this->UpdateContactAboutText(hContact, contact); + break; + case CContact::P_AUTHREQ_TIMESTAMP: + { + uint newTS = 0; + contact->GetPropAuthreqTimestamp(newTS); + DWORD oldTS = this->GetSettingDword(hContact, "AuthTS"); + if (newTS > oldTS) + { + char* sid = ::mir_utf8decodeA((const char*)data); + + contact->GetPropDisplayname(data); + char* nick = ::mir_utf8decodeA((const char*)data); + + contact->GetPropReceivedAuthrequest(data); + char* reason = ::mir_utf8decodeA((const char*)data); + + //todo: add first/last name + this->RaiseAuthRequestEvent(newTS, sid, nick, "", "", reason); + } + } + break; + case CContact::P_AUTHREQUEST_COUNT: + // todo: all authrequests after first should be catch here + this->UpdateContactAuthState(hContact, contact); + break; + case CContact::P_AVAILABILITY: + this->UpdateContactStatus(hContact, contact); + break; + case CContact::P_AVATAR_IMAGE: + case CContact::P_AVATAR_TIMESTAMP: + this->UpdateContactAvatar(hContact, contact); + break; + case CContact::P_BIRTHDAY: + this->UpdateContactBirthday(hContact, contact); + break; + case CContact::P_CITY: + this->UpdateContactCity(hContact, contact); + break; + case CContact::P_COUNTRY: + this->UpdateContactCountry(hContact, contact); + break; + case CContact::P_EMAILS: + this->UpdateContactEmails(hContact, contact); + break; + case CContact::P_GENDER: + this->UpdateContactGender(hContact, contact); + break; + case CContact::P_HOMEPAGE: + this->UpdateContactHomepage(hContact, contact); + break; + case CContact::P_LANGUAGES: + this->UpdateContactLanguages(hContact, contact); + break; + case CContact::P_MOOD_TEXT: + case CContact::P_MOOD_TIMESTAMP: + this->UpdateContactStatusMessage(hContact, contact); + break; + case CContact::P_PHONE_HOME: + this->UpdateContactPhone(hContact, contact); + break; + case CContact::P_PHONE_MOBILE: + this->UpdateContactMobilePhone(hContact, contact); + break; + case CContact::P_PHONE_OFFICE: + this->UpdateContactOfficePhone(hContact, contact); + break; + case CContact::P_PROFILE_TIMESTAMP: + this->UpdateContactProfile(hContact, contact); + break; + case CContact::P_PROVINCE: + this->UpdateContactState(hContact, contact); + break; + case CContact::P_TIMEZONE: + this->UpdateContactTimezone(hContact, contact); + break; } } + //else + //{ + // switch(prop) + // { + // case CContact::P_RECEIVED_AUTHREQUEST: + // contact->GetPropDisplayname(data); + // wchar_t* displayName = ::mir_a2u((const char*)data); + + // CCSDATA ccs = {0}; + // ccs.szProtoService = PSR_AUTH; + // ccs.hContact = this->AddContactBySkypeName(skypeName, displayName, PALF_TEMPORARY); + // //pre.szMessage = (LPSTR)btBuff; + // //CreateBlobFromContact(ccs.hContact, lpwszMessage, dwMessageSize, btBuff, SIZEOF(btBuff), (size_t*)&pre.lParam); + // CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs); + // break; + // } + //} + + //if (prop == CContact::P_AVAILABILITY) + //{ + // SEString data; + + // contact->GetPropSkypename(data); + // wchar_t* skypeName = ::mir_a2u((const char*)data); + + // HANDLE hContact = this->GetContactBySkypeName(skypeName); + // if (hContact) + // { + // CContact::AVAILABILITY availability; + // contact->GetPropAvailability(availability); + // this->SetSettingWord(hContact, SKYPE_SETTINGS_STATUS, this->SkypeToMirandaStatus(availability)); + + // if (availability == CContact::PENDINGAUTH) + // this->SetSettingWord(hContact, "Auth", 1); + // else + // this->DeleteSetting(hContact, "Auth"); + // } + //} +} + +void CSkypeProto::OnContactListChanged(const ContactRef& contact) +{ + CContactGroup::TYPE type; + this->contactList->GetPropType(type); + //switch (type) + //{ + //case CContactGroup::ALL_KNOWN_CONTACTS: + // if ( !this->contactList->Contains(contact)) + // { + // SEString data; + + // contact->GetPropSkypename(data); + // wchar_t* sid = ::mir_utf8decodeW((const char*)data); + // + // contact->GetPropDisplayname(data); + // wchar_t* nick = ::mir_utf8decodeW((const char*)data); + // + // contact->GetPropReceivedAuthrequest(data); + // wchar_t* reason = ::mir_utf8decodeW((const char*)data); + + // uint newTS = 0; + // contact->GetPropAuthreqTimestamp(newTS); + // + // //todo: add first/last name + // this->RaiseAuthRequestEvent(newTS, sid, nick, L"", L"", reason); + // } + // break; + //} } bool CSkypeProto::IsProtoContact(HANDLE hContact) @@ -29,17 +451,14 @@ bool CSkypeProto::IsProtoContact(HANDLE hContact) return ::CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM)hContact, (LPARAM)this->m_szModuleName) < 0; } -HANDLE CSkypeProto::GetContactBySkypeName(wchar_t* skypeName) +HANDLE CSkypeProto::GetContactBySid(const wchar_t* sid) { HANDLE hContact = (HANDLE)::CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); while (hContact) { if (this->IsProtoContact(hContact)) { - wchar_t* data = this->GetSettingString(hContact, "SkypeName", L""); - bool result = ::wcscmp(skypeName, data) == 0; - mir_free(data); - if (result) + if (::wcscmp(sid, this->GetSettingString(hContact, "sid", L"")) == 0) return hContact; } @@ -49,16 +468,36 @@ HANDLE CSkypeProto::GetContactBySkypeName(wchar_t* skypeName) return 0; } -HANDLE CSkypeProto::AddContactBySkypeName(wchar_t* skypeName, wchar_t* displayName, DWORD flags) +HANDLE CSkypeProto::GetContactFromAuthEvent(HANDLE hEvent) +{ + DWORD body[3]; + DBEVENTINFO dbei = { sizeof(DBEVENTINFO) }; + dbei.cbBlob = sizeof(DWORD) * 2; + dbei.pBlob = (PBYTE)&body; + + if (::CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbei)) + return INVALID_HANDLE_VALUE; + + if (dbei.eventType != EVENTTYPE_AUTHREQUEST) + return INVALID_HANDLE_VALUE; + + if (strcmp(dbei.szModule, this->m_szModuleName) != 0) + return INVALID_HANDLE_VALUE; + + return ::DbGetAuthEventContact(&dbei); +} + +HANDLE CSkypeProto::AddContactBySid(const wchar_t* sid, const wchar_t* nick, DWORD flags) { - HANDLE hContact = this->GetContactBySkypeName(skypeName); + HANDLE hContact = this->GetContactBySid(sid); if ( !hContact) { hContact = (HANDLE)::CallService(MS_DB_CONTACT_ADD, 0, 0); ::CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)this->m_szModuleName); - this->SetSettingString(hContact, "SkypeName", skypeName); - this->SetSettingString(hContact, "Nick", displayName); + this->SetSettingString(hContact, "sid", sid); + + this->SetSettingString(hContact, "Nick", nick); //::DBWriteContactSettingWString(hContact, "CList", "MyHandle", displayName); if (flags & PALF_TEMPORARY) @@ -69,7 +508,7 @@ HANDLE CSkypeProto::AddContactBySkypeName(wchar_t* skypeName, wchar_t* displayNa } else { - if (!(flags & PALF_TEMPORARY)) + if ( !(flags & PALF_TEMPORARY)) ::DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1); } @@ -101,6 +540,27 @@ int CSkypeProto::SkypeToMirandaStatus(CContact::AVAILABILITY availability) return status; } +void CSkypeProto::RemoveContact(HANDLE hContact) +{ + if (this->IsOnline() && hContact) + { + //bool canDelete = false; + CContact::Ref contact; + SEString sid(::mir_u2a(this->GetSettingString(hContact, "sid"))); + g_skype->GetContact(sid, contact); + contact->SetBuddyStatus(CContact::BLOCKED_BY_ME); + + //this->contactList->CanRemoveContact(canDelete); + //if (canDelete) + { + contact->SetBuddyStatus(false/*CContact::BLOCKED_BY_ME*/); + this->contactList->ContactList.remove_val(contact); + this->contactList->RemoveContact(contact); + this->contactList.fetch(); + } + } +} + CContact::AVAILABILITY CSkypeProto::MirandaToSkypeStatus(int status) { CContact::AVAILABILITY availability = CContact::UNKNOWN; @@ -127,151 +587,47 @@ CContact::AVAILABILITY CSkypeProto::MirandaToSkypeStatus(int status) return availability; } -void CSkypeProto::LoadContactInfo(HANDLE hContact, CContact::Ref contact) -{ - CContact::AVAILABILITY availability; - contact->GetPropAvailability(availability); - this->SetSettingWord(hContact, SKYPE_SETTINGS_STATUS, this->SkypeToMirandaStatus(availability)); - - if (availability == CContact::PENDINGAUTH) - this->SetSettingWord(hContact, "Auth", 1); - else - this->DeleteSetting(hContact, "Auth"); - - uint newTS = 0; - DWORD oldTS = 0; - - // profile info - contact->GetPropProfileTimestamp(newTS); - oldTS = this->GetSettingDword(hContact, "ProfileUpdateTS"); - //if (newTS > oldTS) - { - uint uData; - SEString sData; - // birth date - contact->GetPropBirthday(uData); - if (uData > 0) - { - struct tm* ptm; - time_t timeGMT = (time_t)uData; - ptm = gmtime(&timeGMT); - this->SetSettingByte(hContact, "BirthDay", ptm->tm_mday); - this->SetSettingByte(hContact, "BirthMonth", ptm->tm_mon); - this->SetSettingWord(hContact, "BirthYear", ptm->tm_year + 1917); - } - // gender - contact->GetPropGender(uData); - this->SetSettingByte(hContact, "Gender", (BYTE)(uData ? 'M' : 'F')); - // timezone - contact->GetPropTimezone(uData); - if (uData > 0) - this->SetSettingByte(hContact, "TimeZone", uData); - else - this->DeleteSetting(hContact, "TimeZone"); - // language - contact->GetPropLanguages(sData); - // country (en, ru, etc) - contact->GetPropCountry(sData); - BYTE countryId = this->GetCountryIdByName((const char*)sData); - this->SetSettingByte(hContact, "Country", countryId); - // state - contact->GetPropProvince(sData); - this->SetSettingString(hContact, "State", ::mir_a2u((const char*)sData)); - // city - contact->GetPropCity(sData); - this->SetSettingString(hContact, "City", ::mir_a2u((const char*)sData)); - // home phone - contact->GetPropPhoneHome(sData); - this->SetSettingString(hContact, "Phone", ::mir_a2u((const char*)sData)); - // office phone - contact->GetPropPhoneOffice(sData); - this->SetSettingString(hContact, "CompanyPhone", ::mir_a2u((const char*)sData)); - // mobile phone - contact->GetPropPhoneMobile(sData); - this->SetSettingString(hContact, "Cellular", ::mir_a2u((const char*)sData)); - // e-mail - contact->GetPropEmails(sData); - this->SetSettingString(hContact, "e-mail", ::mir_a2u((const char*)sData)); - // homepage - contact->GetPropHomepage(sData); - this->SetSettingString(hContact, "Homepage", ::mir_a2u((const char*)sData)); - // about - contact->GetPropAbout(sData); - this->SetSettingString(hContact, "About", ::mir_a2u((const char*)sData)); - // profile update ts - this->SetSettingDword(hContact, "ProfileUpdateTS", newTS); - } - - // mood text - contact->GetPropProfileTimestamp(newTS); - oldTS = this->GetSettingDword(hContact, "XStatusTS"); - if (newTS > oldTS) - { - SEString status; - contact->GetPropAbout(status); - this->SetSettingString(hContact, "XStatusMsg", ::mir_a2u((const char*)status)); - // mood text update ts - this->SetSettingDword(hContact, "XStatusTS", newTS); - } - - // avatar - contact->GetPropProfileTimestamp(newTS); - oldTS = this->GetSettingDword(hContact, "AvatarTS"); - if (newTS > oldTS) - { - SEBinary avatar; - contact->GetPropAvatarImage(avatar); - - if (avatar.size() > 0) - { - FILE* fp = _wfopen(this->GetAvatarFilePath(this->GetSettingString(hContact, "SkypeName")), L"w"); - for (int i = 0; i < avatar.size(); i++) - { - if (i) - fputc(',', fp); - fputc('\'', fp); - switch(avatar[i]) - { - case '\n': - fputc('\\', fp); - fputc('n', fp); - break; - - default: - fputc(avatar[i], fp); - } - } - CloseHandle(fp); - } - // todo: need to register avatar to contact - //avatar update ts - this->SetSettingDword(hContact, "AvatarTS", newTS); - } -} - void __cdecl CSkypeProto::LoadContactList(void*) { - g_skype->GetHardwiredContactGroup(CContactGroup::ALL_KNOWN_CONTACTS, this->contactGroup); - - this->contactGroup->GetContacts(this->contactGroup->ContactList); - Sid::fetch(this->contactGroup->ContactList); - - for (unsigned int i = 0; i < this->contactGroup->ContactList.size(); i++) + g_skype->GetHardwiredContactGroup(CContactGroup::ALL_KNOWN_CONTACTS, this->contactList); + this->contactList.fetch(); + this->contactList->SetOnContactListChangedCallback( + (CContactGroup::OnContactListChanged)&CSkypeProto::OnContactListChanged, + this); + this->contactList->GetContacts(this->contactList->ContactList); + Sid::fetch(this->contactList->ContactList); + + for (unsigned int i = 0; i < this->contactList->ContactList.size(); i++) { - CContact::Ref contact = this->contactGroup->ContactList[i]; - contact->SetOnContactChangeCallback((OnContactChangeFunc)&CSkypeProto::OnContactChanged, this); + CContact::Ref contact = this->contactList->ContactList[i]; + contact->SetOnContactChangedCallback( + (CContact::OnContactChanged)&CSkypeProto::OnContactChanged, + this); SEString data; contact->GetPropSkypename(data); - wchar_t* skypeName = ::mir_a2u((const char*)data); + wchar_t* sid = ::mir_utf8decodeW((const char*)data); contact->GetPropDisplayname(data); - wchar_t* displayName = :: mir_utf8decodeW((const char*)data); + wchar_t* nick = ::mir_utf8decodeW((const char*)data); + + contact->GetPropFullname(data); + wchar_t* name = ::mir_utf8decodeW((const char*)data); + + DWORD flags = 0; + CContact::AVAILABILITY availability; + contact->GetPropAvailability(availability); + if (availability == CContact::PENDINGAUTH) + flags = PALF_TEMPORARY; - HANDLE hContact = this->AddContactBySkypeName(skypeName, displayName, 0); + HANDLE hContact = this->AddContactBySid(sid, nick, flags); - this->LoadContactInfo(hContact, contact); + this->UpdateContactAuthState(hContact, contact); + this->UpdateContactAvatar(hContact, contact); + this->UpdateContactProfile(hContact, contact); + this->UpdateContactStatus(hContact, contact); + this->UpdateContactStatusMessage(hContact, contact); } } diff --git a/protocols/Skype/src/skype_database.cpp b/protocols/Skype/src/skype_database.cpp new file mode 100644 index 0000000000..b22c632be0 --- /dev/null +++ b/protocols/Skype/src/skype_database.cpp @@ -0,0 +1,55 @@ +#include "skype_proto.h" + +HANDLE CSkypeProto::AddDataBaseEvent(HANDLE hContact, WORD type, DWORD time, DWORD flags, DWORD cbBlob, PBYTE pBlob) +{ + DBEVENTINFO dbei = {0}; + + dbei.cbSize = sizeof(dbei); + dbei.szModule = this->m_szModuleName; + dbei.timestamp = time; + dbei.flags = flags; + dbei.eventType = type; + dbei.cbBlob = cbBlob; + dbei.pBlob = pBlob; + + return (HANDLE)CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei); +} + +void CSkypeProto::RaiseAuthRequestEvent( + DWORD timestamp, + const char* sid, + const char* nick, + const char* firstName, + const char* lastName, + const char* reason) +{ + PROTORECVEVENT pre = {0}; + + CCSDATA ccs = {0}; + ccs.szProtoService = PSR_AUTH; + ccs.hContact = this->GetContactBySid(::mir_a2u(sid)); + ccs.wParam = 0; + ccs.lParam = (LPARAM)⪯ + pre.timestamp = timestamp; + pre.lParam = (DWORD) + (sizeof(DWORD) * 2) + + ::strlen(nick) + + ::strlen(firstName) + + ::strlen(lastName) + + ::strlen(sid) + + ::strlen(reason) + + 5; + + /*blob is: 0(DWORD), hContact(DWORD), nick(ASCIIZ), firstName(ASCIIZ), lastName(ASCIIZ), sid(ASCIIZ), reason(ASCIIZ)*/ + char *pCurBlob = pre.szMessage = (char*)::mir_alloc(pre.lParam); + + *((PDWORD)pCurBlob) = 0; pCurBlob += sizeof(DWORD); + *((PDWORD)pCurBlob) = (DWORD)ccs.hContact; pCurBlob += sizeof(DWORD); + ::strcpy((char*)pCurBlob, nick); pCurBlob += ::strlen(nick) + 1; + ::strcpy((char*)pCurBlob, firstName); pCurBlob += ::strlen(sid) + 1; + ::strcpy((char*)pCurBlob, lastName); pCurBlob += ::strlen(sid) + 1; + ::strcpy((char*)pCurBlob, sid); pCurBlob += ::strlen(sid) + 1; + ::strcpy((char*)pCurBlob, reason); + + ::CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs); +} \ No newline at end of file diff --git a/protocols/Skype/src/skype_events.cpp b/protocols/Skype/src/skype_events.cpp index 1546ed6e85..ef97109d6f 100644 --- a/protocols/Skype/src/skype_events.cpp +++ b/protocols/Skype/src/skype_events.cpp @@ -13,3 +13,10 @@ int CSkypeProto::OnPreShutdown(WPARAM, LPARAM) return 0; } + +int CSkypeProto::OnContactDeleted(WPARAM wParam, LPARAM) +{ + this->RemoveContact((HANDLE)wParam); + + return 0; +} diff --git a/protocols/Skype/src/skype_proto.cpp b/protocols/Skype/src/skype_proto.cpp index e4c6170c76..75f2686eae 100644 --- a/protocols/Skype/src/skype_proto.cpp +++ b/protocols/Skype/src/skype_proto.cpp @@ -34,10 +34,10 @@ CSkypeProto::~CSkypeProto() HANDLE __cdecl CSkypeProto::AddToList(int flags, PROTOSEARCHRESULT* psr) { - if (psr->cbSize != sizeof(PROTOSEARCHRESULT)) + //if (psr->cbSize != sizeof(PROTOSEARCHRESULT)) return 0; - return this->AddContactBySkypeName(psr->id, psr->nick, flags); + //return this->AddContactBySkypeName(psr->id, psr->nick, flags); } HANDLE __cdecl CSkypeProto::AddToListByEvent(int flags, int iContact, HANDLE hDbEvent) @@ -45,7 +45,7 @@ HANDLE __cdecl CSkypeProto::AddToListByEvent(int flags, int iContact, HANDLE hDb DBEVENTINFO dbei = {0}; dbei.cbSize = sizeof(dbei); - if ((dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0)) != -1) + /*if ((dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0)) != -1) { dbei.pBlob = (PBYTE)alloca(dbei.cbBlob); if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei) == 0 && @@ -58,14 +58,85 @@ HANDLE __cdecl CSkypeProto::AddToListByEvent(int flags, int iContact, HANDLE hDb char *skypeName = lastName + strlen(lastName) + 1; return AddContactBySkypeName(::mir_a2u(skypeName), ::mir_a2u(nick), 0); } + }*/ + return 0; +} + +int __cdecl CSkypeProto::Authorize(HANDLE hDbEvent) +{ + if (this->IsOnline() && hDbEvent) + { + HANDLE hContact = this->GetContactFromAuthEvent(hDbEvent); + if (hContact == INVALID_HANDLE_VALUE) + return 1; + + CContact::Ref contact; + SEString sid(::mir_u2a(this->GetSettingString(hContact, "sid"))); + g_skype->GetContact(sid, contact); + contact->SetBuddyStatus(true/*Contact::AUTHORIZED_BY_ME*/); + + return 0; } + + return 1; +} + +int __cdecl CSkypeProto::AuthDeny(HANDLE hDbEvent, const TCHAR* szReason) +{ + if (this->IsOnline()) + { + HANDLE hContact = this->GetContactFromAuthEvent(hDbEvent); + if (hContact == INVALID_HANDLE_VALUE) + return 1; + + CContact::Ref contact; + SEString sid(::mir_u2a(this->GetSettingString(hContact, "SkypeName"))); + g_skype->GetContact(sid, contact); + contact->SetBuddyStatus(false/*CContact::BLOCKED_BY_ME*/); + + return 0; + } + + return 1; +} + +int __cdecl CSkypeProto::AuthRecv(HANDLE hContact, PROTORECVEVENT* pre) +{ + DWORD flags = 0; + + if (pre->flags & PREF_CREATEREAD) + flags |= DBEF_READ; + + if (pre->flags & PREF_UTF) + flags |= DBEF_UTF; + + this->AddDataBaseEvent( + hContact, + EVENTTYPE_AUTHREQUEST, + pre->timestamp, + flags, + pre->lParam, + (PBYTE)pre->szMessage); + return 0; } -int __cdecl CSkypeProto::Authorize( HANDLE hDbEvent ) { return 0; } -int __cdecl CSkypeProto::AuthDeny( HANDLE hDbEvent, const TCHAR* szReason ) { return 0; } -int __cdecl CSkypeProto::AuthRecv( HANDLE hContact, PROTORECVEVENT* ) { return 0; } -int __cdecl CSkypeProto::AuthRequest( HANDLE hContact, const TCHAR* szMessage ) { return 0; } +int __cdecl CSkypeProto::AuthRequest(HANDLE hContact, const TCHAR* szMessage) +{ + if (this->IsOnline() && hContact) + { + CContact::Ref contact; + SEString sid(::mir_u2a(this->GetSettingString(hContact, "SkypeName"))); + g_skype->GetContact(sid, contact); + + contact->SendAuthRequest(::mir_u2a(szMessage)); + this->DeleteSetting(hContact, "Grant"); + + return 0; + } + + return 1; +} HANDLE __cdecl CSkypeProto::ChangeInfo( int iInfoType, void* pInfoData ) { return 0; } @@ -153,8 +224,8 @@ int CSkypeProto::SetStatus(int new_status) this->m_iStatus = ID_STATUS_CONNECTING; this->password = this->GetDecodeSettingString(SKYPE_SETTINGS_PASSWORD); - this->ForkThread(&CSkypeProto::SignIn, this); - //this->SignIn(this); + //this->ForkThread(&CSkypeProto::SignIn, this); + this->SignIn(this); } } @@ -180,10 +251,13 @@ int __cdecl CSkypeProto::OnEvent(PROTOEVENTTYPE eventType, WPARAM wParam, LPA switch (eventType) { case EV_PROTO_ONLOAD: - return this->OnModulesLoaded(0, 0); + return this->OnModulesLoaded(wParam, lParam); case EV_PROTO_ONEXIT: - return this->OnPreShutdown(0, 0); + return this->OnPreShutdown(wParam, lParam); + + case EV_PROTO_ONCONTACTDELETED: + return this->OnContactDeleted(wParam, lParam); } return 1; @@ -201,4 +275,9 @@ void __cdecl CSkypeProto::SignIn(void*) //this->LoadContactList(this); ReleaseMutex(this->signin_lock); +} + +bool CSkypeProto::IsOnline() +{ + return this->m_iStatus != ID_STATUS_OFFLINE; } \ No newline at end of file diff --git a/protocols/Skype/src/skype_proto.h b/protocols/Skype/src/skype_proto.h index 8ae37492c8..37d869d581 100644 --- a/protocols/Skype/src/skype_proto.h +++ b/protocols/Skype/src/skype_proto.h @@ -79,6 +79,7 @@ public: // events int __cdecl OnModulesLoaded(WPARAM, LPARAM); int __cdecl OnPreShutdown(WPARAM, LPARAM); + int __cdecl OnContactDeleted(WPARAM, LPARAM); int __cdecl OnOptionsInit(WPARAM, LPARAM); int __cdecl OnAccountManagerInit(WPARAM wParam, LPARAM lParam); @@ -103,7 +104,7 @@ public: protected: CAccount::Ref account; - CContactGroup::Ref contactGroup; + CContactGroup::Ref contactList; TCHAR* login; TCHAR* password; @@ -111,19 +112,42 @@ protected: HANDLE signin_lock; void __cdecl SignIn(void*); - void LoadContactInfo(HANDLE hContact, CContact::Ref contact); - void __cdecl LoadContactList(void*); + bool IsOnline(); // contacts - void OnContactChanged(CContact* contact, int prop); + void UpdateContactAboutText(HANDLE hContact, CContact::Ref contact); + void UpdateContactAuthState(HANDLE hContact, CContact::Ref contact); + void UpdateContactAvatar(HANDLE hContact, CContact::Ref contact); + void UpdateContactBirthday(HANDLE hContact, CContact::Ref contact); + void UpdateContactCity(HANDLE hContact, CContact::Ref contact); + void UpdateContactCountry(HANDLE hContact, CContact::Ref contact); + void UpdateContactEmails(HANDLE hContact, CContact::Ref contact); + void UpdateContactGender(HANDLE hContact, CContact::Ref contact); + void UpdateContactHomepage(HANDLE hContact, CContact::Ref contact); + void UpdateContactLanguages(HANDLE hContact, CContact::Ref contact); + void UpdateContactMobilePhone(HANDLE hContact, CContact::Ref contact); + void UpdateContactPhone(HANDLE hContact, CContact::Ref contact); + void UpdateContactOfficePhone(HANDLE hContact, CContact::Ref contact); + void UpdateContactState(HANDLE hContact, CContact::Ref contact); + void UpdateContactStatus(HANDLE hContact, CContact::Ref contact); + void UpdateContactStatusMessage(HANDLE hContact, CContact::Ref contact); + void UpdateContactTimezone(HANDLE hContact, CContact::Ref contact); + void UpdateContactProfile(HANDLE hContact, CContact::Ref contact); + + void OnContactChanged(CContact::Ref contact, int prop); + void OnContactListChanged(const ContactRef& contact); bool IsProtoContact(HANDLE hContact); - HANDLE AddContactBySkypeName(wchar_t* skypeName, wchar_t* displayName, DWORD flags); - HANDLE GetContactBySkypeName(wchar_t* skypeName); + HANDLE GetContactBySid(const wchar_t* sid); + HANDLE GetContactFromAuthEvent(HANDLE hEvent); + HANDLE AddContactBySid(const wchar_t* skypeName, const wchar_t* nick, DWORD flags = 0); + void RemoveContact(HANDLE hContact); int SkypeToMirandaStatus(CContact::AVAILABILITY availability); CContact::AVAILABILITY MirandaToSkypeStatus(int status); void SetAllContactStatus(int status); + void __cdecl LoadContactList(void*); + // utils static char* GetCountryNameById(int countryId); static int GetCountryIdByName(const char* countryName); @@ -163,6 +187,16 @@ protected: int OnPrebuildContactMenu(WPARAM wParam, LPARAM); + // database + HANDLE AddDataBaseEvent(HANDLE hContact, WORD type, DWORD time, DWORD flags, DWORD cbBlob, PBYTE pBlob); + void RaiseAuthRequestEvent( + DWORD timestamp, + const char* sid, + const char* nick, + const char* firstName = "", + const char* lastName = "", + const char* reason = ""); + // database settings BYTE GetSettingByte(const char *setting, BYTE errorValue = 0); BYTE GetSettingByte(HANDLE hContact, const char *setting, BYTE errorValue = 0); @@ -181,10 +215,10 @@ protected: bool SetSettingWord(HANDLE hContact, const char *setting, WORD value); bool SetSettingDword(const char *setting, DWORD value); bool SetSettingDword(HANDLE hContact, const char *setting, DWORD value); - bool SetSettingString(const char *setting, wchar_t* value); - bool SetSettingString(HANDLE hContact, const char *setting, wchar_t* value); - bool SetDecodeSettingString(const char *setting, wchar_t* value); - bool SetDecodeSettingString(HANDLE hContact, const char *setting, wchar_t* value); + bool SetSettingString(const char *setting, const wchar_t* value); + bool SetSettingString(HANDLE hContact, const char *setting, const wchar_t* value); + bool SetDecodeSettingString(const char *setting, const wchar_t* value); + bool SetDecodeSettingString(HANDLE hContact, const char *setting, const wchar_t* value); // void DeleteSetting(const char *setting); void DeleteSetting(HANDLE hContact, const char *setting); diff --git a/protocols/Skype/src/skype_settings.cpp b/protocols/Skype/src/skype_settings.cpp index 5cbe890268..88826fb613 100644 --- a/protocols/Skype/src/skype_settings.cpp +++ b/protocols/Skype/src/skype_settings.cpp @@ -33,7 +33,7 @@ DWORD CSkypeProto::GetSettingDword(const char *setting, DWORD errorValue) wchar_t* CSkypeProto::GetSettingString(HANDLE hContact, const char *setting, wchar_t* errorValue) { DBVARIANT dbv; - TCHAR* result = NULL; + wchar_t* result = NULL; if ( !::DBGetContactSettingWString(hContact, this->m_szModuleName, setting, &dbv)) { @@ -98,17 +98,17 @@ bool CSkypeProto::SetSettingDword(const char *setting, DWORD value) return this->SetSettingDword(NULL, setting, value); } -bool CSkypeProto::SetSettingString(HANDLE hContact, const char *szSetting, wchar_t* value) +bool CSkypeProto::SetSettingString(HANDLE hContact, const char *szSetting, const wchar_t* value) { return !::DBWriteContactSettingWString(hContact, this->m_szModuleName, szSetting, value); } -bool CSkypeProto::SetSettingString(const char *szSetting, wchar_t* value) +bool CSkypeProto::SetSettingString(const char *szSetting, const wchar_t* value) { return this->SetSettingString(NULL, szSetting, value); } -bool CSkypeProto::SetDecodeSettingString(HANDLE hContact, const char *setting, wchar_t* value) +bool CSkypeProto::SetDecodeSettingString(HANDLE hContact, const char *setting, const wchar_t* value) { TCHAR* result = mir_wstrdup(value); CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(result), reinterpret_cast(result)); @@ -116,7 +116,7 @@ bool CSkypeProto::SetDecodeSettingString(HANDLE hContact, const char *setting, w return !this->SetSettingString(hContact, setting, result); } -bool CSkypeProto::SetDecodeSettingString(const char *setting, wchar_t* value) +bool CSkypeProto::SetDecodeSettingString(const char *setting, const wchar_t* value) { return this->SetDecodeSettingString(NULL, setting, value); } diff --git a/protocols/Skype/src/skype_subclassing.cpp b/protocols/Skype/src/skype_subclassing.cpp index bb943a708e..c7752eeca9 100644 --- a/protocols/Skype/src/skype_subclassing.cpp +++ b/protocols/Skype/src/skype_subclassing.cpp @@ -1,5 +1,7 @@ #include "skype_subclassing.h" +// CSkype + CAccount* CSkype::newAccount(int oid) { return new CAccount(oid, this); @@ -15,6 +17,13 @@ CContact* CSkype::newContact(int oid) return new CContact(oid, this); } +CConversation* CSkype::newConversation(int oid) +{ + return new CConversation(oid, this); +} + +// CAccount + CAccount::CAccount(unsigned int oid, SERootObject* root) : Account(oid, root) { this->isLoggedOut = true; @@ -55,14 +64,32 @@ void CAccount::BlockWhileLoggingOut() Sleep(1); } +// CContactGroup + CContactGroup::CContactGroup(unsigned int oid, SERootObject* root) : ContactGroup(oid, root) { + this->proto = NULL; + this->callback == NULL; +} + +void CContactGroup::SetOnContactListChangedCallback(OnContactListChanged callback, CSkypeProto* proto) +{ + this->proto = proto; + this->callback = callback; +} + +bool CContactGroup::Contains(const ContactRef& contact) +{ + return this->ContactList.contains(contact); } void CContactGroup::OnChange(const ContactRef& contact) { + if (this->proto) + (proto->*callback)(contact); } +// CContact CContact::CContact(unsigned int oid, SERootObject* root) : Contact(oid, root) { @@ -70,7 +97,7 @@ CContact::CContact(unsigned int oid, SERootObject* root) : Contact(oid, root) this->callback == NULL; } -void CContact::SetOnContactChangeCallback(OnContactChangeFunc callback, CSkypeProto* proto) +void CContact::SetOnContactChangedCallback(OnContactChanged callback, CSkypeProto* proto) { this->proto = proto; this->callback = callback; @@ -78,6 +105,15 @@ void CContact::SetOnContactChangeCallback(OnContactChangeFunc callback, CSkypePr void CContact::OnChange(int prop) { - if (this->callback && this->proto) - (proto->*callback)(this, prop); + if (this->proto) + (proto->*callback)(this->ref(), prop); +} + +// Conversation + +CConversation::CConversation(unsigned int oid, SERootObject* root) : Conversation(oid, root) {} + +void CConversation::OnMessage(const MessageRef & message) +{ + // Message handling goes here } \ No newline at end of file diff --git a/protocols/Skype/src/skype_subclassing.h b/protocols/Skype/src/skype_subclassing.h index a4ea9a1264..bef67606a8 100644 --- a/protocols/Skype/src/skype_subclassing.h +++ b/protocols/Skype/src/skype_subclassing.h @@ -5,25 +5,35 @@ #include -class CContact; struct CSkypeProto; -typedef void (CSkypeProto::* OnContactChangeFunc)(CContact* contact, int); +class CConversation : public Conversation +{ +public: + typedef DRef Ref; + typedef DRefs Refs; + + CConversation(unsigned int oid, SERootObject* root);// : Conversation(oid, root) {}; + +protected: + void OnMessage(const MessageRef & message); +}; class CContact : public Contact { public: + typedef void (CSkypeProto::* OnContactChanged)(CContact::Ref contact, int); + typedef DRef Ref; typedef DRefs Refs; CContact(unsigned int oid, SERootObject* root); - void SetOnContactChangeCallback(OnContactChangeFunc callback, CSkypeProto* proto); + void SetOnContactChangedCallback(OnContactChanged callback, CSkypeProto* proto); private: - CSkypeProto* proto; - - OnContactChangeFunc callback; + CSkypeProto* proto; + OnContactChanged callback; void OnChange(int prop); }; @@ -31,13 +41,21 @@ private: class CContactGroup : public ContactGroup { public: + typedef void (CSkypeProto::* OnContactListChanged)(const ContactRef& contact); + typedef DRef Ref; typedef DRefs Refs; CContactGroup(unsigned int oid, SERootObject* root); CContact::Refs ContactList; + void SetOnContactListChangedCallback(OnContactListChanged callback, CSkypeProto* proto); + + bool Contains(const ContactRef& contact); private: + CSkypeProto* proto; + OnContactListChanged callback; + void OnChange(const ContactRef& contact); }; @@ -63,5 +81,6 @@ class CSkype : public Skype public: CAccount* newAccount(int oid); CContactGroup* newContactGroup(int oid); + CConversation* newConversation(int oid); CContact* newContact(int oid); }; \ No newline at end of file -- cgit v1.2.3