summaryrefslogtreecommitdiff
path: root/protocols/Skype/src
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Skype/src')
-rw-r--r--protocols/Skype/src/skype_contacts.cpp672
-rw-r--r--protocols/Skype/src/skype_database.cpp55
-rw-r--r--protocols/Skype/src/skype_events.cpp7
-rw-r--r--protocols/Skype/src/skype_proto.cpp101
-rw-r--r--protocols/Skype/src/skype_proto.h54
-rw-r--r--protocols/Skype/src/skype_settings.cpp10
-rw-r--r--protocols/Skype/src/skype_subclassing.cpp42
-rw-r--r--protocols/Skype/src/skype_subclassing.h31
8 files changed, 779 insertions, 193 deletions
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;
+ 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<LPARAM>(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 <skype-embedded_2.h>
-class CContact;
struct CSkypeProto;
-typedef void (CSkypeProto::* OnContactChangeFunc)(CContact* contact, int);
+class CConversation : public Conversation
+{
+public:
+ typedef DRef<CConversation, Conversation> Ref;
+ typedef DRefs<CConversation, Conversation> 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<CContact, Contact> Ref;
typedef DRefs<CContact, Contact> 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<CContactGroup, ContactGroup> Ref;
typedef DRefs<CContactGroup, ContactGroup> 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