/*
Copyright (c) 2015 Miranda NG project (http://miranda-ng.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "common.h"
CSkypeProto::CSkypeProto(const char* protoName, const TCHAR* userName) :
PROTO(protoName, userName), password(NULL)
{
m_hProtoIcon = Icons[0].Handle;
SetAllContactsStatus(ID_STATUS_OFFLINE);
wchar_t name[128];
mir_sntprintf(name, SIZEOF(name), TranslateT("%s connection"), m_tszUserName);
NETLIBUSER nlu = { 0 };
nlu.cbSize = sizeof(nlu);
nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_HTTPCONNS | NUF_UNICODE;
nlu.ptszDescriptiveName = name;
nlu.szSettingsModule = m_szModuleName;
m_hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
requestQueue = new RequestQueue(m_hNetlibUser);
CreateProtoService(PS_CREATEACCMGRUI, &CSkypeProto::OnAccountManagerInit);
CreateProtoService(PS_GETAVATARINFOT, &CSkypeProto::SvcGetAvatarInfo);
CreateProtoService(PS_GETAVATARCAPS, &CSkypeProto::SvcGetAvatarCaps);
CreateProtoService(PS_GETMYAVATART, &CSkypeProto::SvcGetMyAvatar);
CreateProtoService(PS_SETMYAVATART, &CSkypeProto::SvcSetMyAvatar);
m_tszAvatarFolder = std::tstring(VARST(_T("%miranda_avatarcache%"))) + _T("\\") + m_tszUserName;
DWORD dwAttributes = GetFileAttributes(m_tszAvatarFolder.c_str());
if (dwAttributes == 0xffffffff || (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
CreateDirectoryTreeT(m_tszAvatarFolder.c_str());
// custom event
DBEVENTTYPEDESCR dbEventType = { sizeof(dbEventType) };
dbEventType.module = m_szModuleName;
dbEventType.flags = DETF_HISTORY | DETF_MSGWINDOW;
dbEventType.eventType = SKYPE_DB_EVENT_TYPE_ACTION;
dbEventType.descr = Translate("Action");
CallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&dbEventType);
}
CSkypeProto::~CSkypeProto()
{
delete requestQueue;
Netlib_CloseHandle(m_hNetlibUser);
m_hNetlibUser = NULL;
}
DWORD_PTR CSkypeProto::GetCaps(int type, MCONTACT)
{
switch (type)
{
case PFLAGNUM_1:
return PF1_IM | PF1_AUTHREQ | PF1_CHAT | PF1_BASICSEARCH;
case PFLAGNUM_2:
return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_HEAVYDND;
case PFLAGNUM_3:
return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_HEAVYDND;
case PFLAGNUM_4:
return PF4_FORCEADDED | PF4_NOAUTHDENYREASON | PF4_SUPPORTTYPING | PF4_AVATARS | PF4_IMSENDOFFLINE | PF4_IMSENDUTF;
case PFLAG_UNIQUEIDTEXT:
return (INT_PTR)"Skypename";
case PFLAG_UNIQUEIDSETTING:
return (DWORD_PTR)SKYPE_SETTINGS_ID;
}
return 0;
}
MCONTACT CSkypeProto::AddToList(int flags, PROTOSEARCHRESULT *psr)
{
debugLogA("CSkypeProto::AddToList");
ptrA skypeName(mir_t2a(ptrT(psr->id)));
if (skypeName == NULL)
return NULL;
MCONTACT hContact = AddContact(skypeName);
return hContact;
}
MCONTACT CSkypeProto::AddToListByEvent(int, int, MEVENT) { return 0; }
int CSkypeProto::Authorize(MEVENT hDbEvent)
{
MCONTACT hContact = GetContactFromAuthEvent(hDbEvent);
if (hContact == INVALID_CONTACT_ID)
return 1;
ptrA token(getStringA("TokenSecret"));
ptrA skypename(getStringA(hContact, SKYPE_SETTINGS_ID));
PushRequest(new AuthAcceptRequest(token, skypename));
return 0;
}
int CSkypeProto::AuthDeny(MEVENT hDbEvent, const PROTOCHAR*)
{
MCONTACT hContact = GetContactFromAuthEvent(hDbEvent);
if (hContact == INVALID_CONTACT_ID)
return 1;
ptrA token(getStringA("TokenSecret"));
ptrA skypename(getStringA(hContact, SKYPE_SETTINGS_ID));
PushRequest(new AuthDeclineRequest(token, skypename));
return 0;
}
int CSkypeProto::AuthRecv(MCONTACT, PROTORECVEVENT* pre)
{
return Proto_AuthRecv(m_szModuleName, pre);
}
int CSkypeProto::AuthRequest(MCONTACT hContact, const PROTOCHAR *szMessage)
{
if (hContact == INVALID_CONTACT_ID)
return 1;
ptrA token(getStringA("TokenSecret"));
ptrA skypename(getStringA(hContact, SKYPE_SETTINGS_ID));
PushRequest(new AddContactRequest(token, skypename, ptrA(mir_t2a(szMessage))));
return 0;
}
int CSkypeProto::GetInfo(MCONTACT hContact, int)
{
PushRequest(
new GetProfileRequest(ptrA(getStringA("TokenSecret")), ptrA(db_get_sa(hContact, m_szModuleName, SKYPE_SETTINGS_ID))),
&CSkypeProto::LoadProfile);
return 0;
}
int CSkypeProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre)
{
return SaveMessageToDb(hContact, pre);
}
int CSkypeProto::SendMsg(MCONTACT hContact, int flags, const char *msg)
{
return OnSendMessage(hContact, flags, msg);
}
int CSkypeProto::SetStatus(int iNewStatus)
{
if (iNewStatus == m_iDesiredStatus)
return 0;
debugLogA(__FUNCTION__ ": changing status from %i to %i", m_iStatus, iNewStatus);
int old_status = m_iStatus;
m_iDesiredStatus = iNewStatus;
if (iNewStatus == ID_STATUS_OFFLINE)
{
// logout
isTerminated = true;
if (m_pollingConnection)
CallService(MS_NETLIB_SHUTDOWN, (WPARAM)m_pollingConnection, 0);
if (m_iStatus > ID_STATUS_CONNECTING + 1)
{
SendRequest(new DeleteEndpointRequest(RegToken, EndpointId, Server));
delSetting("registrationRoken");
delSetting("endpointId");
delSetting("expires");
}
requestQueue->Stop();
if (!Miranda_Terminated())
SetAllContactsStatus(ID_STATUS_OFFLINE);
m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
}
else
{
if (old_status == ID_STATUS_CONNECTING)
return 0;
if (old_status == ID_STATUS_OFFLINE && m_iStatus == ID_STATUS_OFFLINE)
{
// login
m_iStatus = ID_STATUS_CONNECTING;
requestQueue->Start();
int tokenExpires(getDword("TokenExpiresIn", 0));
if ((tokenExpires - 1800) > time(NULL))
OnLoginSuccess();
else
PushRequest(new LoginRequest(), &CSkypeProto::OnLoginFirst);
}
else
{
// set status
SendRequest(new SetStatusRequest(RegToken, MirandaToSkypeStatus(m_iDesiredStatus)), &CSkypeProto::OnStatusChanged);
PushRequest(new SendCapabilitiesRequest(RegToken, EndpointId));
}
}
ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus);
return 0;
}
int CSkypeProto::UserIsTyping(MCONTACT hContact, int type)
{
SendRequest(new SendTypingRequest(RegToken, ptrA(getStringA(hContact, SKYPE_SETTINGS_ID)), type, Server));
return 0;
}
int CSkypeProto::OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam)
{
switch (iEventType)
{
case EV_PROTO_ONLOAD:
return OnAccountLoaded(wParam, lParam);
case EV_PROTO_ONCONTACTDELETED:
return OnContactDeleted(wParam, lParam);
case EV_PROTO_ONMENU:
return OnInitStatusMenu();
}
return 1;
}