/*
Copyright (c) 2015-18 Miranda NG team (https://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 .
*/
#ifndef _SKYPE_PROTO_H_
#define _SKYPE_PROTO_H_
typedef void(CSkypeProto::*SkypeResponseCallback)(const NETLIBHTTPREQUEST *response);
typedef void(CSkypeProto::*SkypeResponseWithArgCallback)(const NETLIBHTTPREQUEST *response, void *arg);
struct CSkypeProto : public PROTO < CSkypeProto >
{
friend CSkypeOptionsMain;
friend CSkypeGCCreateDlg;
public:
//////////////////////////////////////////////////////////////////////////////////////
//Ctors
CSkypeProto(const char *protoName, const wchar_t *userName);
~CSkypeProto();
//////////////////////////////////////////////////////////////////////////////////////
// Virtual functions
MCONTACT AddToList(int flags, PROTOSEARCHRESULT* psr) override;
MCONTACT AddToListByEvent(int flags, int iContact, MEVENT hDbEvent) override;
int AuthRequest(MCONTACT hContact, const wchar_t* szMessage) override;
int Authorize(MEVENT hDbEvent) override;
int AuthDeny(MEVENT hDbEvent, const wchar_t* szReason) override;
int AuthRecv(MCONTACT hContact, PROTORECVEVENT*) override;
INT_PTR GetCaps(int type, MCONTACT hContact = NULL) override;
int GetInfo(MCONTACT hContact, int infoType) override;
HANDLE SearchBasic(const wchar_t* id) override;
int SendMsg(MCONTACT hContact, int flags, const char* msg) override;
int SetStatus(int iNewStatus) override;
int UserIsTyping(MCONTACT hContact, int type) override;
int RecvContacts(MCONTACT hContact, PROTORECVEVENT*) override;
HANDLE SendFile(MCONTACT hContact, const wchar_t *szDescription, wchar_t **ppszFiles) override;
HANDLE GetAwayMsg(MCONTACT hContact) override;
int SetAwayMsg(int m_iStatus, const wchar_t *msg) override;
void OnBuildProtoMenu(void) override;
void OnContactDeleted(MCONTACT) override;
void OnModulesLoaded() override;
void OnShutdown() override;
// icons
static void InitIcons();
// menus
static void InitMenus();
//popups
void InitPopups();
void UninitPopups();
// languages
static void InitLanguages();
// events
static int OnModulesLoaded(WPARAM, LPARAM);
int __cdecl OnDbEventRead(WPARAM, LPARAM);
// search
void __cdecl SearchBasicThread(void* id);
////////////////////////////////////////////
static INT_PTR EventGetIcon(WPARAM wParam, LPARAM lParam);
static INT_PTR GetEventText(WPARAM, LPARAM lParam);
CSkypeOptions m_opts;
private:
LoginInfo li;
struct contacts_list
{
CSkypeProto *m_proto;
std::map m_cache;
contacts_list(CSkypeProto *ppro) : m_proto(ppro)
{}
~contacts_list()
{
for (auto it = m_cache.begin(); it != m_cache.end(); ++it)
{
mir_free(it->second);
}
}
const char* operator[](MCONTACT hContact)
{
try
{
return m_cache.at(hContact);
}
catch (std::out_of_range&)
{
char *id = m_proto->getStringA(hContact, SKYPE_SETTINGS_ID);
m_cache[hContact] = id;
return id;
}
}
} Contacts;
static UINT_PTR m_timer;
RequestQueue *requestQueue;
bool m_bHistorySynced;
std::map m_mpOutMessages;
std::map cookies;
static std::map languages;
HNETLIBCONN m_pollingConnection, m_TrouterConnection;
HANDLE m_hPollingThread, m_hTrouterThread;
TRInfo TRouter;
LIST m_PopupClasses;
LIST m_OutMessages;
//dialogs
LIST m_InviteDialogs;
LIST m_GCCreateDialogs;
//locks
mir_cs m_lckOutMessagesList;
mir_cs m_InviteDialogsLock;
mir_cs m_GCCreateDialogsLock;
mir_cs messageSyncLock;
mir_cs m_StatusLock;
mir_cs m_AppendMessageLock;
static mir_cs accountsLock;
static mir_cs timerLock;
bool m_bThreadsTerminated;
EventHandle m_hPollingEvent;
EventHandle m_hTrouterEvent;
EventHandle m_hTrouterHealthEvent;
INT_PTR __cdecl OnAccountManagerInit(WPARAM, LPARAM);
std::wstring m_tszAvatarFolder;
INT_PTR __cdecl SvcGetAvatarInfo(WPARAM, LPARAM);
INT_PTR __cdecl SvcGetAvatarCaps(WPARAM, LPARAM);
INT_PTR __cdecl SvcGetMyAvatar(WPARAM, LPARAM);
INT_PTR __cdecl SvcSetMyAvatar(WPARAM, LPARAM);
int InternalSetAvatar(MCONTACT hContact, const char *szJid, const wchar_t *ptszFileName);
// requests
void InitNetwork();
void UnInitNetwork();
void ShutdownConnections();
void PushRequest(HttpRequest *request);
void PushRequest(HttpRequest *request, SkypeResponseCallback response);
void PushRequest(HttpRequest *request, SkypeResponseWithArgCallback response, void *arg);
template
void PushRequest(HttpRequest *request, F callback)
{
SkypeResponseDelegateBase *delegate = new SkypeResponseDelegateLambda(this, callback);
requestQueue->Push(request, SkypeHttpResponse, delegate);
}
void SendRequest(HttpRequest *request);
void SendRequest(HttpRequest *request, SkypeResponseCallback response);
void SendRequest(HttpRequest *request, SkypeResponseWithArgCallback response, void *arg);
template
void SendRequest(HttpRequest *request, F callback)
{
SkypeResponseDelegateBase *delegate = new SkypeResponseDelegateLambda(this, response);
requestQueue->Send(request, SkypeHttpResponse, delegate);
}
// icons
static HICON GetIcon(int iconId);
static HANDLE GetIconHandle(int iconId);
// menus
static HGENMENU ContactMenuItems[CMI_MAX];
int OnPrebuildContactMenu(WPARAM hContact, LPARAM);
static int PrebuildContactMenu(WPARAM hContact, LPARAM lParam);
// options
int __cdecl OnOptionsInit(WPARAM wParam, LPARAM lParam);
// oauth
void OnOAuthStart(const NETLIBHTTPREQUEST *response);
void OnOAuthAuthorize(const NETLIBHTTPREQUEST *response);
void OnOAuthEnd(const NETLIBHTTPREQUEST *response);
// login
void Login();
void OnMSLoginFirst(const NETLIBHTTPREQUEST *response);
void OnMSLoginSecond(const NETLIBHTTPREQUEST *response);
void OnMSLoginThird(const NETLIBHTTPREQUEST *response);
void OnMSLoginEnd(const NETLIBHTTPREQUEST *response);
void OnLoginOAuth(const NETLIBHTTPREQUEST *response);
void OnLoginSuccess();
void OnEndpointCreated(const NETLIBHTTPREQUEST *response);
void SendPresence(bool isLogin = false);
void OnSubscriptionsCreated(const NETLIBHTTPREQUEST *response);
void OnCapabilitiesSended(const NETLIBHTTPREQUEST *response);
void OnStatusChanged(const NETLIBHTTPREQUEST *response);
//TRouter
void OnCreateTrouter(const NETLIBHTTPREQUEST *response);
void OnTrouterPoliciesCreated(const NETLIBHTTPREQUEST *response);
void OnGetTrouter(const NETLIBHTTPREQUEST *response);
void OnHealth(const NETLIBHTTPREQUEST *response);
void OnTrouterEvent(const JSONNode &body, const JSONNode &headers);
void __cdecl TRouterThread(void*);
// profile
void UpdateProfileFirstName(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileLastName(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileDisplayName(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileGender(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileBirthday(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileCountry(const JSONNode &node, MCONTACT hContact = NULL);
void UpdateProfileState(const JSONNode &node, MCONTACT hContact = NULL);
void UpdateProfileCity(const JSONNode &node, MCONTACT hContact = NULL);
void UpdateProfileLanguage(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileHomepage(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileAbout(const JSONNode &node, MCONTACT hContact = NULL);
void UpdateProfileEmails(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfilePhoneMobile(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfilePhoneHome(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfilePhoneOffice(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileXStatusMessage(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileAvatar(const JSONNode &root, MCONTACT hContact = NULL);
void LoadProfile(const NETLIBHTTPREQUEST *response, void *arg);
void __cdecl CSkypeProto::SendFileThread(void *p);
void OnASMObjectCreated(const NETLIBHTTPREQUEST *response, void *arg);
void OnASMObjectUploaded(const NETLIBHTTPREQUEST *response, void *arg);
// contacts
WORD GetContactStatus(MCONTACT hContact);
void SetContactStatus(MCONTACT hContact, WORD status);
void SetAvatarUrl(MCONTACT hContact, CMStringW &tszUrl);
void ReloadAvatarInfo(MCONTACT hContact);
void GetAvatarFileName(MCONTACT hContact, wchar_t* pszDest, size_t cbLen);
void OnReceiveAvatar(const NETLIBHTTPREQUEST *response, void *arg);
void OnSentAvatar(const NETLIBHTTPREQUEST *response);
void OnSearch(const NETLIBHTTPREQUEST *response);
MCONTACT FindContact(const char *skypename);
MCONTACT AddContact(const char *skypename, bool isTemporary = false);
MCONTACT GetContactFromAuthEvent(MEVENT hEvent);
void LoadContactsAuth(const NETLIBHTTPREQUEST *response);
void LoadContactsInfo(const NETLIBHTTPREQUEST *response);
void LoadContactList(const NETLIBHTTPREQUEST *response);
void OnBlockContact(const NETLIBHTTPREQUEST *response, void *p);
void OnUnblockContact(const NETLIBHTTPREQUEST *response, void *p);
// messages
std::map m_mpOutMessagesIds;
MEVENT GetMessageFromDb(MCONTACT hContact, const char *messageId, LONGLONG timestamp = 0);
MEVENT AddDbEvent(WORD type, MCONTACT hContact, DWORD timestamp, DWORD flags, const char *content, const char *uid);
MEVENT AppendDBEvent(MCONTACT hContact, MEVENT hEvent, const char *szContent, const char *szUid, time_t edit_time);
int OnReceiveMessage(MCONTACT hContact, const char *szContent, const char *szMessageId, time_t timestamp, int emoteOffset = 0, bool isRead = false);
int OnSendMessage(MCONTACT hContact, int flags, const char *message);
void OnMessageSent(const NETLIBHTTPREQUEST *response, void *arg);
int __cdecl OnPreCreateMessage(WPARAM, LPARAM lParam);
void MarkMessagesRead(MCONTACT hContact, MEVENT hDbEvent);
void OnPrivateMessageEvent(const JSONNode &node);
void ProcessContactRecv(MCONTACT hContact, time_t timestamp, const char *szContent, const char *szMessageId);
// sync
void OnGetServerHistory(const NETLIBHTTPREQUEST *response);
void OnSyncHistory(const NETLIBHTTPREQUEST *response);
//chats
void InitGroupChatModule();
MCONTACT FindChatRoom(const char *chatname);
int __cdecl OnGroupChatEventHook(WPARAM, LPARAM lParam);
int __cdecl OnGroupChatMenuHook(WPARAM, LPARAM lParam);
INT_PTR __cdecl OnJoinChatRoom(WPARAM hContact, LPARAM);
INT_PTR __cdecl OnLeaveChatRoom(WPARAM hContact, LPARAM);
void StartChatRoom(const wchar_t *tid, const wchar_t *tname);
void OnLoadChats(const NETLIBHTTPREQUEST *response);
void OnGetChatInfo(const NETLIBHTTPREQUEST *response, void *p);
void OnChatEvent(const JSONNode &node);
void OnSendChatMessage(const wchar_t *chat_id, const wchar_t * tszMessage);
char *GetChatUsers(const wchar_t *chat_id);
bool IsChatContact(const wchar_t *chat_id, const char *id);
void AddMessageToChat(const wchar_t *chat_id, const wchar_t *from, const char *content, bool isAction, int emoteOffset, time_t timestamp, bool isLoading = false);
void AddChatContact(const wchar_t *tchat_id, const char *id, const char *name, const wchar_t *role, bool isChange = false);
void RemoveChatContact(const wchar_t *tchat_id, const char *id, const char *name, bool isKick = false, const char *initiator = "");
wchar_t *GetChatContactNick(const char *chat_id, const char *id, const char *name);
void RenameChat(const char *chat_id, const char *name);
void ChangeChatTopic(const char * chat_id, const char *topic, const char *initiator);
void SetChatStatus(MCONTACT hContact, int iStatus);
//polling
void __cdecl PollingThread (void*);
void __cdecl ParsePollData (const char*);
void ProcessEndpointPresence (const JSONNode &node);
void ProcessUserPresence (const JSONNode &node);
void ProcessNewMessage (const JSONNode &node);
void ProcessConversationUpdate (const JSONNode &node);
void ProcessThreadUpdate (const JSONNode &node);
// utils
template
__inline static void FreeList(const LIST &lst)
{
for (auto &it : lst)
mir_free(it);
}
__forceinline bool IsOnline() const
{ return (m_iStatus > ID_STATUS_OFFLINE);
}
__forceinline bool IsMe(const char *str)
{ return (!mir_strcmpi(str, li.szMyname) || !mir_strcmp(str, ptrA(getStringA("SelfEndpointName"))));
}
MEVENT AddEventToDb(MCONTACT hContact, WORD type, DWORD timestamp, DWORD flags, DWORD cbBlob, PBYTE pBlob);
static time_t IsoToUnixTime(const char *stamp);
static char *RemoveHtml(const char *text);
static CMStringA GetStringChunk(const char *haystack, const char *start, const char *end);
static int SkypeToMirandaStatus(const char *status);
static const char *MirandaToSkypeStatus(int status);
void ShowNotification(const wchar_t *message, MCONTACT hContact = NULL);
void ShowNotification(const wchar_t *caption, const wchar_t *message, MCONTACT hContact = NULL, int type = 0);
static bool IsFileExists(std::wstring path);
static LRESULT CALLBACK PopupDlgProcCall(HWND hPopup, UINT uMsg, WPARAM wParam, LPARAM lParam);
static CMStringA ParseUrl(const char *url, const char *token);
static CMStringA UrlToSkypename(const char *url);
static CMStringA GetServerFromUrl(const char *url);
//---Timers
void CALLBACK SkypeUnsetTimer();
void CALLBACK SkypeSetTimer();
void ProcessTimer();
static void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD);
//---/
time_t GetLastMessageTime(MCONTACT hContact);
CMStringW RunConfirmationCode();
CMStringW ChangeTopicForm();
void CloseDialogs();
//events
void InitDBEvents();
//services
INT_PTR __cdecl OnIncomingCallCLE(WPARAM wParam, LPARAM lParam);
INT_PTR __cdecl OnIncomingCallPP(WPARAM wParam, LPARAM lParam);
INT_PTR __cdecl BlockContact(WPARAM hContact, LPARAM);
INT_PTR __cdecl UnblockContact(WPARAM hContact, LPARAM);
INT_PTR __cdecl OnRequestAuth(WPARAM hContact, LPARAM lParam);
INT_PTR __cdecl OnGrantAuth(WPARAM hContact, LPARAM);
INT_PTR __cdecl GetContactHistory(WPARAM hContact, LPARAM lParam);
INT_PTR __cdecl SvcCreateChat(WPARAM, LPARAM);
INT_PTR __cdecl ParseSkypeUriService(WPARAM, LPARAM lParam);
static INT_PTR __cdecl GlobalParseSkypeUriService(WPARAM, LPARAM lParam);
template
static INT_PTR __cdecl GlobalService(WPARAM wParam, LPARAM lParam)
{
CSkypeProto *proto = CMPlugin::getInstance((MCONTACT)wParam);
return proto ? (proto->*Service)(wParam, lParam) : 0;
}
};
struct CMPlugin : public ACCPROTOPLUGIN
{
CMPlugin();
int Load() override;
int Unload() override;
};
#endif //_SKYPE_PROTO_H_